X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fdinit-log.cc;h=43062f0f15a400ca938c7d188be6b9f9d5dcc28b;hb=100650949c81204d8d52002e028aa8858a406bce;hp=431c2a5eed5d71d53adef599efba33667daa4d6c;hpb=5de5713bfceb31da2fbbc0d33569177fee056a34;p=oweals%2Fdinit.git diff --git a/src/dinit-log.cc b/src/dinit-log.cc index 431c2a5..43062f0 100644 --- a/src/dinit-log.cc +++ b/src/dinit-log.cc @@ -4,8 +4,9 @@ #include #include #include +#include -#include "dasync.h" +#include "dasynq.h" #include "service.h" #include "dinit-log.h" @@ -19,7 +20,7 @@ LogLevel log_level[2] = { LogLevel::WARN, LogLevel::WARN }; static ServiceSet *service_set = nullptr; // Reference to service set namespace { -class BufferedLogStream : public PosixFdWatcher +class BufferedLogStream : public EventLoop_t::FdWatcher { private: @@ -105,7 +106,7 @@ void BufferedLogStream::flushForRelease() // Try to flush any messages that are currently buffered. (Console is non-blocking // so it will fail gracefully). - if (gotEvent(&eventLoop, fd, out_events) == Rearm::DISARM) { + if (gotEvent(&eventLoop, fd, OUT_EVENTS) == Rearm::DISARM) { // Console has already been released at this point. setEnabled(&eventLoop, false); } @@ -153,8 +154,14 @@ Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept return Rearm::DISARM; } - char *ptr = log_stream.log_buffer.get_ptr(0); - int len = log_stream.log_buffer.get_contiguous_length(ptr); + // We try to find a complete line (terminated by '\n') in the buffer, and write it + // out. Since it may span the circular buffer end, it may consist of two distinct spans, + // and so we use writev to write them atomically. + + struct iovec logiov[2]; + + char *ptr = log_buffer.get_ptr(0); + int len = log_buffer.get_contiguous_length(ptr); char *creptr = ptr + len; // contiguous region end char *eptr = std::find(ptr, creptr, '\n'); @@ -166,7 +173,27 @@ Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept len = eptr - ptr; - int r = write(fd, ptr, len); + logiov[0].iov_base = ptr; + logiov[0].iov_len = len; + int iovs_to_write = 1; + + // Do we need the second span? + if (! will_complete && len != log_buffer.get_length()) { + ptr = log_buffer.get_buf_base(); + creptr = static_cast(logiov[1].iov_base) + log_buffer.get_length() - len; + eptr = std::find(ptr, creptr, '\n'); + if (eptr != creptr) { + eptr++; // include '\n' + // It should not ever be the case that we do not now have a complete message + will_complete = true; + } + logiov[1].iov_base = ptr; + logiov[1].iov_len = eptr - ptr; + len += logiov[1].iov_len; + iovs_to_write = 2; + } + + ssize_t r = writev(fd, logiov, iovs_to_write); if (r >= 0) { bool complete = (r == len) && will_complete; @@ -196,7 +223,7 @@ Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept void init_log(ServiceSet *sset) { service_set = sset; - log_stream[DLOG_CONS].registerWith(&eventLoop, STDOUT_FILENO, out_events); // TODO register in disabled state + log_stream[DLOG_CONS].registerWith(&eventLoop, STDOUT_FILENO, OUT_EVENTS); // TODO register in disabled state enable_console_log(true); } @@ -205,7 +232,7 @@ void init_log(ServiceSet *sset) void setup_main_log(int fd) { log_stream[DLOG_MAIN].init(fd); - log_stream[DLOG_MAIN].registerWith(&eventLoop, fd, out_events); + log_stream[DLOG_MAIN].registerWith(&eventLoop, fd, OUT_EVENTS); } bool is_log_flushed() noexcept