From f7311a2127f49a1530e34184425ea5801734dd6b Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Fri, 7 Jan 2022 17:46:46 +0100 Subject: add global logging support (G) --- rvnit.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/rvnit.c b/rvnit.c index 6e8de20..77cd4bd 100644 --- a/rvnit.c +++ b/rvnit.c @@ -54,6 +54,9 @@ pthread_t logger_thread; int selflogfd[2]; int newlogfd[2]; +int globallogfd[2]; + +int use_global_log; sig_atomic_t want_shutdown; sig_atomic_t want_rescan; @@ -119,6 +122,11 @@ restart(int i) } } + if (services[i].name[2] == 'G') { + // enable global logger + use_global_log = 1; + } + pid_t child = fork(); if (child == 0) { dup2(services[i].logfd[1], 1); @@ -127,6 +135,13 @@ restart(int i) close(loggerpipe[0]); close(loggerpipe[1]); } + if (services[i].name[2] == 'G') { + // global loggers get read end of global log pipe + dup2(globallogfd[0], 0); + + // global loggers write to stderr, to avoid lopos + dup2(2, 1); + } close(services[i].logfd[0]); close(services[i].logfd[1]); @@ -245,6 +260,7 @@ socket_loop(void* ignored) pthread_mutex_lock(&services_lock); for (int i = 0; i < MAX_SV; i++) { if (services[i].name[2] == 'D' || + services[i].name[2] == 'G' || services[i].name[2] == 'L') dprintf(connfd, "%-25s pid=%d state=%s uptime=%ld status=%d\n", services[i].name, @@ -387,10 +403,12 @@ logger_loop(void* ignored) const char *sv = ""; long pid = -1; + int pass_thru = 0; if (fds[j].fd == selflogfd[0]) { sv = "rvnit"; pid = getpid(); + pass_thru = (level != 100); } else { pthread_mutex_lock(&services_lock); for (int i = 0; i < MAX_SV; i++) { @@ -410,9 +428,23 @@ logger_loop(void* ignored) if (!eol) eol = e; - printf("%s.%05ld %s[%ld]: %.*s\n", - timestamp, now.tv_nsec / 10000, - sv, pid, (int)(eol - s), s); + int r = 0; + if (use_global_log) { + r = dprintf(globallogfd[1], + "%s.%05ld %s[%ld]: %.*s\n", + timestamp, now.tv_nsec / 10000, + sv, pid, (int)(eol - s), s); + } + if (!use_global_log || pass_thru || r < 0) { + /* print own messages, and messages + during boot/shutdown, or when writing + to logger failed (potentially because + the pipe is full, we don't want to + stall here) */ + dprintf(2, "%s.%05ld %s[%ld]: %.*s\n", + timestamp, now.tv_nsec / 10000, + sv, pid, (int)(eol - s), s); + } s = eol + 1; } @@ -595,6 +627,12 @@ main(int argc, char *argv[]) fcntl(newlogfd[0], F_SETFD, FD_CLOEXEC); fcntl(newlogfd[1], F_SETFD, FD_CLOEXEC); + pipe(globallogfd); + // don't care about read end + fcntl(globallogfd[1], F_SETFL, O_NONBLOCK); + fcntl(globallogfd[0], F_SETFD, FD_CLOEXEC); + fcntl(globallogfd[1], F_SETFD, FD_CLOEXEC); + if (pthread_mutex_init(&services_lock, 0) != 0) { perror("pthread_mutex_init"); return 111; @@ -635,7 +673,7 @@ main(int argc, char *argv[]) restart(i); } - // spawn oneshots and daemons + // spawn oneshots, daemons, global logger for (i = 0; i < MAX_SV; i++) { if (services[i].level != level) continue; @@ -648,6 +686,8 @@ main(int argc, char *argv[]) oneshot++; } else if (services[i].name[2] == 'D') { restart(i); + } else if (services[i].name[2] == 'G') { + restart(i); } } @@ -688,6 +728,7 @@ main(int argc, char *argv[]) oneshot--; } else if (services[i].name[2] == 'D' || + services[i].name[2] == 'G' || services[i].name[2] == 'L') { restart(i); } @@ -740,6 +781,18 @@ cont1: kill(services[i].pid, SIGTERM); } } + for (i = 0; i < MAX_SV; i++) { + if (services[i].name[2] == 'G') { + if (services[i].state == UP && + services[i].pid == 0) + restart(i); + if (services[i].state == DOWN && + services[i].pid > 0) { + kill(services[i].pid, SIGTERM); + use_global_log = 0; + } + } + } pthread_mutex_unlock(&services_lock); want_rescan = 0; @@ -763,6 +816,7 @@ cont1: goto cont2; if (services[i].name[2] == 'D' || + services[i].name[2] == 'G' || services[i].name[2] == 'L') { LOG("%s terminated with status %d", services[i].name, services[i].status); if (services[i].state == UP) { @@ -917,6 +971,8 @@ cont4: else dprintf(selflogfd[1], "shutdown\n"); + close(globallogfd[1]); + close(selflogfd[1]); pthread_join(logger_thread, 0); } -- cgit 1.4.1