From: Davin McCall Date: Sat, 11 Jun 2016 19:38:22 +0000 (+0100) Subject: Enable logging to syslog. X-Git-Tag: v0.02 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=a2c7e27fbe7e95b41bc485aad425c2e5158f1709;p=oweals%2Fdinit.git Enable logging to syslog. --- diff --git a/src/dinit-log.cc b/src/dinit-log.cc index 64767d4..1ad961c 100644 --- a/src/dinit-log.cc +++ b/src/dinit-log.cc @@ -3,6 +3,7 @@ #include #include +#include #include "dasync.h" @@ -115,7 +116,7 @@ void BufferedLogStream::flushForRelease() Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept { auto &log_stream = *this; - + if ((! partway) && log_stream.special) { char * start = log_stream.special_buf + log_stream.msg_index; char * end = std::find(log_stream.special_buf + log_stream.msg_index, (char *)nullptr, '\n'); @@ -137,9 +138,8 @@ Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept return Rearm::REARM; } } - else { - // spurious readiness, or EAGAIN/EWOULDBLOCK/EINTR - // There's not much we can do for other errors anyway. + else if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) { + return Rearm::REMOVE; } return Rearm::REARM; } @@ -148,7 +148,7 @@ Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept // TODO issue special message if we have discarded a log message - if (log_stream.current_index == 0) { + if (current_index == 0) { release_console(); return Rearm::DISARM; } @@ -181,6 +181,9 @@ Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept } } } + else if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) { + return Rearm::REMOVE; + } } // We've written something by the time we get here. We could fall through to below, but @@ -201,8 +204,8 @@ void init_log(ServiceSet *sset) // Potentially throws std::bad_alloc or std::system_error void setup_main_log(int fd) { - log_stream[DLOG_MAIN].init(STDERR_FILENO); - log_stream[DLOG_MAIN].registerWith(&eventLoop, STDERR_FILENO, out_events); + log_stream[DLOG_MAIN].init(fd); + log_stream[DLOG_MAIN].registerWith(&eventLoop, fd, out_events); } bool is_log_flushed() noexcept @@ -237,7 +240,7 @@ static int sum_length(const char *arg) noexcept return std::strlen(arg); } -template static int sum_length(U first, T ... args) noexcept +template static int sum_length(const char * first, T ... args) noexcept { return sum_length(first) + sum_length(args...); } @@ -248,7 +251,7 @@ static void append(BufferedLogStream &buf, const char *s) buf.append(s, std::strlen(s)); } -template static void append(BufferedLogStream &buf, U u, T ... t) +template static void append(BufferedLogStream &buf, const char *u, T ... t) { append(buf, u); append(buf, t...); @@ -289,7 +292,11 @@ template static void do_log_main(T ... args) noexcept { log_current_line[DLOG_CONS] = false; log_current_line[DLOG_MAIN] = true; - push_to_log(args...); + + char svcbuf[10]; + snprintf(svcbuf, 10, "<%d> ", LOG_DAEMON | LOG_NOTICE); + + push_to_log(svcbuf, args...); } // Log a message. A newline will be appended. @@ -314,12 +321,6 @@ template static void do_log_part(int idx, T arg) noexcept } } -// Log part of a message. A series of calls to do_log_part must be followed by a call to do_log_commit. -template static void do_log_part(T arg) noexcept -{ - do_log_part(DLOG_CONS, arg); -} - // Commit a message that was issued as a series of parts (via do_log_part). static void do_log_commit(int idx) noexcept { diff --git a/src/dinit.cc b/src/dinit.cc index 8315af1..a82f502 100644 --- a/src/dinit.cc +++ b/src/dinit.cc @@ -65,15 +65,11 @@ using EventLoop_t = EventLoop; EventLoop_t eventLoop = EventLoop_t(); -// TODO remove: -//static void sigint_reboot_cb(struct ev_loop *loop, ev_signal *w, int revents); -//static void sigquit_cb(struct ev_loop *loop, ev_signal *w, int revents); -//static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents); static void sigint_reboot_cb(EventLoop_t *eloop) noexcept; static void sigquit_cb(EventLoop_t *eloop) noexcept; static void sigterm_cb(EventLoop_t *eloop) noexcept; -void open_control_socket(EventLoop_t *loop) noexcept; -void close_control_socket(EventLoop_t *loop) noexcept; +static void open_control_socket(EventLoop_t *loop) noexcept; +static void close_control_socket(EventLoop_t *loop) noexcept; static void control_socket_cb(EventLoop_t *loop, int fd); @@ -106,6 +102,7 @@ static ServiceSet *service_set; static bool am_system_init = false; // true if we are the system init process static bool control_socket_open = false; +static bool external_log_open = false; int active_control_conns = 0; // Control socket path. We maintain a string (control_socket_str) in case we need @@ -113,6 +110,8 @@ int active_control_conns = 0; static const char *control_socket_path = "/dev/dinitctl"; static std::string control_socket_str; +static const char *log_socket_path = "/dev/log"; + static const char *user_home_path = nullptr; @@ -300,7 +299,6 @@ int main(int argc, char **argv) } // Set up signal handlers - //ev_signal sigint_ev_signal; CallbackSignalHandler sigint_watcher; if (am_system_init) { sigint_watcher.setCbFunc(sigint_reboot_cb); @@ -425,7 +423,6 @@ int main(int argc, char **argv) // PID 1 must not actually exit, although we should never reach this point: while (true) { - // ev_loop(loop, EVLOOP_ONESHOT); eventLoop.run(); } } @@ -454,7 +451,7 @@ static void control_socket_cb(EventLoop_t *loop, int sockfd) } } -void open_control_socket(EventLoop_t *loop) noexcept +static void open_control_socket(EventLoop_t *loop) noexcept { if (! control_socket_open) { const char * saddrname = control_socket_path; @@ -508,17 +505,14 @@ void open_control_socket(EventLoop_t *loop) noexcept } control_socket_open = true; - //ev_io_init(&control_socket_io, control_socket_cb, sockfd, EV_READ); - //ev_io_start(loop, &control_socket_io); control_socket_io.registerWith(&eventLoop, sockfd, in_events); } } -void close_control_socket(EventLoop_t *loop) noexcept +static void close_control_socket(EventLoop_t *loop) noexcept { if (control_socket_open) { int fd = control_socket_io.fd; - //ev_io_stop(loop, &control_socket_io); control_socket_io.deregisterWatch(&eventLoop); close(fd); @@ -527,6 +521,59 @@ void close_control_socket(EventLoop_t *loop) noexcept } } +static void setup_external_log() noexcept +{ + if (! external_log_open) { + + const char * saddrname = log_socket_path; + uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + strlen(saddrname) + 1; + + struct sockaddr_un * name = static_cast(malloc(sockaddr_size)); + if (name == nullptr) { + log(LogLevel::ERROR, "Connecting to log socket: out of memory"); + return; + } + + name->sun_family = AF_UNIX; + strcpy(name->sun_path, saddrname); + + int sockfd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); + if (sockfd == -1) { + log(LogLevel::ERROR, "Error creating log socket: ", strerror(errno)); + free(name); + return; + } + + if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) { + // TODO for EINPROGRESS, set up a watcher so we can properly wait until + // connection is established (or fails) before we pass it to the logging subsystem. + try { + setup_main_log(sockfd); + } + catch (std::exception &e) { + log(LogLevel::ERROR, "Setting up log failed: ", e.what()); + close(sockfd); + } + } + else { + // Note if connect fails, we haven't warned at all, because the syslog server might not + // have started yet. TODO, have a special startup flag to indicate when syslog should + // be available. + close(sockfd); + } + + free(name); + } +} + +// Called from service when the system is "rw ready" (filesystem mounted r/w etc). +// May be called more than once. +void system_rw_ready() noexcept +{ + open_control_socket(&eventLoop); + setup_external_log(); +} + /* handle SIGINT signal (generated by kernel when ctrl+alt+del pressed) */ static void sigint_reboot_cb(EventLoop_t *eloop) noexcept { diff --git a/src/service.cc b/src/service.cc index 47ba9de..b3bbf16 100644 --- a/src/service.cc +++ b/src/service.cc @@ -23,7 +23,7 @@ */ // from dinit.cc: -void open_control_socket(EventLoop_t *loop) noexcept; +void system_rw_ready() noexcept; extern EventLoop_t eventLoop; // Find the requested service by name @@ -558,7 +558,7 @@ void ServiceRecord::started() noexcept notifyListeners(ServiceEvent::STARTED); if (onstart_flags.rw_ready) { - open_control_socket(&eventLoop); + system_rw_ready(); } if (force_stop || desired_state == ServiceState::STOPPED) {