1 #include "reader_logger.h"
2 #include "reader_common.h"
3 #include "logger_internal.h"
5 #include <buffer_traits.h>
10 static void free_reader_logger(struct reader_common *_reader)
12 struct reader_logger *const reader = (struct reader_logger *) _reader;
15 list_remove(&_reader->server->readers, reader);
17 if (reader->device_fd != -1)
18 close(reader->device_fd);
20 /* We don't do `pthread_cancel(reader->thread);`, the thread should
21 * end on its own (there's some external cleanup involved anyway).
22 * At the moment the thread assumes the reader is permanent and only
23 * closes when the whole program does, which is approximately true. */
26 static void handle_single_log(struct reader_logger *reader, struct now_t time, int read_count)
29 assert(read_count > 0);
31 if (reader->skip_count > 0) {
32 reader->skip_count -= read_count;
36 struct android_logger_entry *const ale = (struct android_logger_entry *) reader->read_buffer;
38 if (read_count < sizeof *ale) {
39 /* This should not happen, but don't treat this as a hard
40 * invariant because kernel bugs happen. Not salvageable. */
42 } else if (read_count == sizeof *ale) {
44 /* Invalid entry. Likely a kernel bug.
45 * At any rate, not salvageable. */
48 /* A "valid" empty entry. Is probably
49 * salvageable (so that the information
50 * that a program tried to log something
51 * and the relevant timestamp are not
52 * completely lost). Maybe later though. */
57 reader->read_buffer[read_count] = '\0';
59 struct dlogutil_entry_with_msg entry;
60 parse_androidlogger_message(ale, &entry.header, read_count);
61 add_recv_timestamp(&entry.header, time);
63 // TODO: Consider calling this in a more robust way (and not having pipe in the name)
64 fixup_pipe_msg(&entry, read_count - sizeof(*ale));
66 // Ignore intermittent write failures. Not a reason to remove the reader.
67 (void) reader_apply_log_to_subs(&reader->common, &entry.header);
71 * @brief Service reader file
72 * @details Handles readers reading directly from file
73 * @param[in] reader The reader to service
74 * @param[in] time Timestamps
75 * @return 0 on success, else an errno value
76 * @return 1 if the reader is to be removed, 0 if kept, -errno on error
78 static int service_reader_logger(struct reader_common *_reader, struct now_t time)
80 struct reader_logger *const reader = (struct reader_logger *) _reader;
84 int r = TEMP_FAILURE_RETRY(read(reader->device_fd, reader->read_buffer, sizeof reader->read_buffer - 1));
88 if (errno == EAGAIN) // no data left in the buffer
94 handle_single_log(reader, time, r);
100 static struct reader_logger *reader_logger_alloc(struct logger *server)
102 struct reader_logger *const ret = calloc(1, sizeof *ret);
106 /* The reader nominally belongs to the server,
107 * but is mostly handled by its own thread. */
108 reader_common_init(&ret->common, server);
112 ret->buf_id = LOG_ID_INVALID;
113 ret->common.service_reader = service_reader_logger;
114 ret->common.free_reader = free_reader_logger;
119 int reader_logger_init(struct reader_logger **reader, log_id_t buf_id, struct logger *server, bool skip)
122 assert(buf_id > LOG_ID_INVALID);
123 assert(buf_id < LOG_ID_MAX);
124 assert(is_core_buffer(buf_id));
126 __attribute__((cleanup(reader_free_ptr))) struct reader_logger *ret = reader_logger_alloc(server);
130 assert(buf_id >= 0 && (unsigned) buf_id < NELEMS(g_backend.logger_devices));
131 char const *config_list = g_backend.logger_devices[buf_id];
132 if (strlen(config_list) == 0)
134 ret->buf_id = buf_id;
136 int r = logger_open_buffer(buf_id, config_list, O_RDONLY | O_NONBLOCK, &ret->device_fd);
140 ret->skip_count = skip ? logger_get_log_len(ret->device_fd) : 0;
142 init_fd_entity(&ret->common.fd_entity_source, dispatch_event_reader, ret);
143 set_read_fd_entity(&ret->common.fd_entity_source, ret->device_fd);
150 static void service_and_maybe_flush(struct reader_logger *const reader)
153 int r = get_now(&now);
157 r = reader->common.service_reader(&reader->common, now);
161 (void) reader_flush(&reader->common, now.mono, reader->common.server->buf_params.time);
164 static void *reader_thread(void *userdata)
166 struct reader_logger *reader = (struct reader_logger *) userdata;
168 struct pollfd fds[2];
169 fds[0].fd = reader->device_fd;
170 fds[0].events = POLLIN;
171 fds[1].fd = reader->common.server->sigmar->wakeup_fde.fd;
172 fds[1].events = POLLIN;
174 while (!reader->common.server->sigmar->exit_signal_received) {
175 int r = poll(fds, NELEMS(fds), reader->common.server->epolltime);
180 /* In theory we spin here; in practice memory
181 * gets overcommitted and mistakes are sorted
182 * by the OOM killer, so spinning is unlikely */
190 service_and_maybe_flush(reader);
193 service_and_maybe_flush(reader);
197 int reader_logger_run(struct reader_logger *reader)
200 int r = pthread_create(&thread, NULL, reader_thread, reader);
204 reader->thread = thread;