*/
static int create_kmsg_writer(struct writer ** writer, struct log_buffer *log_buffer)
{
- int fd = open("/dev/kmsg", O_RDONLY);
+ int fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
if (fd < 0)
return -errno;
return writer_create(writer, fd, log_buffer, service_writer_kmsg, service_socket_dummy);
if (!(event->events & EPOLLIN))
return 0;
- int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
+ /* The KMSG device returns just 1 log per read() so it is done in a loop.
+ * In theory this could starve everything else out if logs appeared faster
+ * than the daemon could process them, which would then necessitate some
+ * sort of throttling. In practice, KMSG doesn't really get flooded with
+ * logs the same way Android Logger devices are so the throttling is mostly
+ * there because we get it for free anyway and consistency doesn't hurt. */
- if (r == -1 && (errno == EAGAIN || errno == EPIPE))
- return 0;
- else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
- return -EINVAL;
- else if (r == 0)
- return -EBADF;
- else if (r == -1)
- return -errno;
+ int max_loop_iterations = g_backend.logger_device_throttling[LOG_ID_KMSG];
+ while (max_loop_iterations--) {
+ int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
- wr->buffer[r] = '\0';
- struct logger_entry_with_msg lem;
- if (parse_kmsg_message(wr->buffer, &lem, r)) {
- // don't signal an error: KMSG writer is too important to remove; besides, it would not get fixed that way.
- return 0;
+ if (r == -1 && (errno == EAGAIN || errno == EPIPE))
+ return 0;
+ else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
+ return -EINVAL;
+ else if (r == 0)
+ return -EBADF;
+ else if (r == -1)
+ return -errno;
+
+ wr->buffer[r] = '\0';
+ struct logger_entry_with_msg lem;
+ if (parse_kmsg_message(wr->buffer, &lem, r)) {
+ // don't signal an error: KMSG writer is too important to remove; besides, it would not get fixed that way.
+ return 0;
+ }
+ add_recv_timestamp(&lem.header);
+ r = buffer_append(&lem.header, wr->buf_ptr);
+ if (r < 0)
+ return r;
}
- add_recv_timestamp(&lem.header);
- return buffer_append(&lem.header, wr->buf_ptr);
+
+ return 0;
}
/**