From 9f0202884c1ad1d00fb71dad7c6dc087f2fb4beb Mon Sep 17 00:00:00 2001 From: Peeter Must Date: Sun, 10 May 2020 11:49:05 +0300 Subject: [PATCH] daemon(8): Make daemon aware of log rotation * Make daemon listen to SIGUSR1 so that when newsyslog has finished log rotation, it can send SIGUSR1 to daemon, who can then reopen the log file specified by the '-o' option. * Failure to open the log file will be logged through syslog with LOG_NOTICE. The next attempt to reopen the log file will be made upon receiving signal SIGUSR1. Reviewed-by: swildner, tuxillo, dillon, aly --- usr.sbin/daemon/daemon.c | 57 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c index 2e6d4f8a16..23b45f8560 100644 --- a/usr.sbin/daemon/daemon.c +++ b/usr.sbin/daemon/daemon.c @@ -65,6 +65,7 @@ struct log_params { static void restrict_process(const char *); static void handle_term(int); static void handle_chld(int); +static void handle_reopen(int); static int listen_child(int, struct log_params *); static int get_log_mapping(const char *, const CODE *); static void open_pid_files(const char *, const char *, struct pidfh **, @@ -74,13 +75,14 @@ static void daemon_sleep(time_t, long); static void usage(void); static volatile sig_atomic_t terminate = 0, child_gone = 0, pid = 0; +static volatile sig_atomic_t reopen = 0; int main(int argc, char *argv[]) { const char *pidfile, *ppidfile, *title, *user, *outfn, *logtag; int ch, nochdir, noclose, restart, dosyslog, child_eof; - sigset_t mask_susp, mask_orig, mask_read, mask_term; + sigset_t mask_susp, mask_orig, mask_read, mask_term, mask_reopen; struct log_params logpar; int pfd[2] = { -1, -1 }, outfd = -1; int stdmask, logpri, logfac; @@ -171,7 +173,7 @@ main(int argc, char *argv[]) if (outfd == -1) err(7, "open"); } - + if (dosyslog) openlog(logtag, LOG_PID | LOG_NDELAY, logfac); @@ -200,7 +202,7 @@ main(int argc, char *argv[]) */ pid = -1; if (pidfile || ppidfile || restart || outfd != -1 || dosyslog) { - struct sigaction act_term, act_chld; + struct sigaction act_term, act_chld, act_reopen; /* Avoid PID racing with SIGCHLD and SIGTERM. */ memset(&act_term, 0, sizeof(act_term)); @@ -213,6 +215,11 @@ main(int argc, char *argv[]) sigemptyset(&act_chld.sa_mask); sigaddset(&act_chld.sa_mask, SIGTERM); + memset(&act_reopen, 0, sizeof(act_reopen)); + act_reopen.sa_handler = handle_reopen; + sigemptyset(&act_reopen.sa_mask); + sigaddset(&act_reopen.sa_mask, SIGUSR1); + /* Block these when avoiding racing before sigsuspend(). */ sigemptyset(&mask_susp); sigaddset(&mask_susp, SIGTERM); @@ -220,6 +227,9 @@ main(int argc, char *argv[]) /* Block SIGTERM when we lack a valid child PID. */ sigemptyset(&mask_term); sigaddset(&mask_term, SIGTERM); + /* Same for SIGUSR1. */ + sigemptyset(&mask_reopen); + sigaddset(&mask_reopen, SIGUSR1); /* * When reading, we wish to avoid SIGCHLD. SIGTERM * has to be caught, otherwise we'll be stuck until @@ -240,6 +250,15 @@ main(int argc, char *argv[]) warn("sigaction"); goto exit; } + /* Block SIGUSR1 until fork. */ + if (sigprocmask(SIG_BLOCK, &mask_reopen, NULL) == -1) { + warn("sigprocmask"); + goto exit; + } + if (sigaction(SIGUSR1, &act_reopen, NULL) == -1) { + warn("sigaction"); + goto exit; + } #ifndef __DragonFly__ /* MADV_PROTECT not supported on DragonFly */ /* * Try to protect against pageout kill. Ignore the @@ -272,6 +291,13 @@ restart: warn("sigprocmask"); goto exit; } + /* + * Unblock SIGUSR1. + */ + if (sigprocmask(SIG_UNBLOCK, &mask_reopen, NULL)) { + warn("sigprocmask"); + goto exit; + } close(pfd[1]); pfd[1] = -1; } @@ -338,6 +364,25 @@ restart: } else if (terminate) { goto exit; } else if (!child_eof) { + if (reopen) { + /* + * Don't close outfd if last open failed. + */ + if (logpar.outfd > 0) + close(logpar.outfd); + if (outfn) { + logpar.outfd = open(outfn, O_CREAT | + O_WRONLY | + O_APPEND | + O_CLOEXEC, + 0600); + if (logpar.outfd == -1) { + syslog(LOG_NOTICE, + "Failed to reopen log file"); + } + } + reopen = 0; + } if (sigprocmask(SIG_BLOCK, &mask_read, NULL)) { warn("sigprocmask"); goto exit; @@ -560,6 +605,12 @@ handle_chld(int signo) } static void +handle_reopen(int signo __attribute__((unused))) +{ + reopen = 1; +} + +static void usage(void) { (void)fprintf(stderr, -- 2.11.4.GIT