diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -106,6 +106,7 @@ #define RCVBUF_MINSIZE (80 * 1024) /* minimum size of dgram rcv buffer */ #include +#include #include #include #include @@ -382,6 +383,11 @@ "FORW", "USERS", "WALL", "PIPE" }; +static int sigcatch[] = { + SIGHUP, SIGINT, SIGQUIT, + SIGALRM, SIGTERM, SIGCHLD, +}; + static bool Debug; /* debug flag */ static bool Foreground = false; /* Run in foreground, instead of daemonizing */ static bool resolve = true; /* resolve hostname */ @@ -411,11 +417,8 @@ static bool KeepKernFac; /* Keep remotely logged kernel facility */ static bool needdofsync = false; /* Are any file(s) waiting to be fsynced? */ static struct pidfh *pfh; -static int sigpipe[2]; /* Pipe to catch a signal during select(). */ static bool RFC3164OutputFormat = true; /* Use legacy format by default. */ -static volatile sig_atomic_t MarkSet, WantDie, WantInitialize, WantReapchild; - struct iovlist; static bool allowaddr(char *); @@ -428,14 +431,12 @@ static int deadq_removebypid(pid_t); static int decode(const char *, const CODE *); static void die(int) __dead2; -static void dodie(int); static void dofsync(void); -static void domark(int); static void fprintlog_first(struct filed *, const char *, const char *, const char *, const char *, const char *, const char *, int); static void fprintlog_write(struct filed *, struct iovlist *, int); static void fprintlog_successive(struct filed *, int); -static void init(int); +static void init(bool); static void logerror(const char *); static void logmsg(int, const struct logtime *, const char *, const char *, const char *, const char *, const char *, const char *, int); @@ -444,8 +445,6 @@ static int socksetup(struct peer *); static int socklist_recv_file(struct socklist *); static int socklist_recv_sock(struct socklist *); -static int socklist_recv_signal(struct socklist *); -static void sighandler(int); static int skip_message(const char *, const char *, int); static int evaluate_prop_filter(const struct prop_filter *filter, const char *value); @@ -454,7 +453,7 @@ static void parsemsg(const char *, char *); static void printsys(char *); static int p_open(const char *, pid_t *); -static void reapchild(int); +static void reapchild(void); static const char *ttymsg_check(struct iovec *, int, char *, int); static void usage(void); static bool validate(struct sockaddr *, const char *); @@ -533,14 +532,15 @@ int main(int argc, char *argv[]) { - int ch, i, s, fdsrmax = 0; - bool bflag = false, pflag = false, Sflag = false; - fd_set *fdsr = NULL; - struct timeval tv, *tvp; - struct peer *pe; + struct timespec ts = { }, *tsp = &ts; + struct kevent ev; struct socklist *sl; - pid_t ppid = 1, spid; + struct peer *pe; + sigset_t sigset = { }; + pid_t ppid = -1, spid; + int ch, kq, error; char *p; + bool bflag = false, pflag = false, Sflag = false; if (madvise(NULL, 0, MADV_PROTECT) != 0) dprintf("madvise() failed: %s\n", strerror(errno)); @@ -714,24 +714,13 @@ if (RFC3164OutputFormat && MaxForwardLen > 1024) errx(1, "RFC 3164 messages may not exceed 1024 bytes"); - /* Pipe to catch a signal during select(). */ - s = pipe2(sigpipe, O_CLOEXEC); - if (s < 0) { - err(1, "cannot open a pipe for signals"); - } else { - addsock(NULL, &(struct socklist){ - .sl_socket = sigpipe[0], - .sl_recv = socklist_recv_signal - }); - } - /* Listen by default: /dev/klog. */ - s = open(_PATH_KLOG, O_RDONLY | O_NONBLOCK | O_CLOEXEC, 0); - if (s < 0) { + error = open(_PATH_KLOG, O_RDONLY | O_NONBLOCK | O_CLOEXEC, 0); + if (error < 0) { dprintf("can't open %s (%d)\n", _PATH_KLOG, errno); } else { addsock(NULL, &(struct socklist){ - .sl_socket = s, + .sl_socket = error, .sl_recv = socklist_recv_file, }); } @@ -776,13 +765,26 @@ (void)strlcpy(consfile.fu_fname, ctty + sizeof _PATH_DEV - 1, sizeof(consfile.fu_fname)); (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile)); - (void)signal(SIGTERM, dodie); - (void)signal(SIGINT, Debug ? dodie : SIG_IGN); - (void)signal(SIGQUIT, Debug ? dodie : SIG_IGN); - (void)signal(SIGHUP, sighandler); - (void)signal(SIGCHLD, sighandler); - (void)signal(SIGALRM, domark); - (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */ + + kq = kqueue(); + if (kq == -1) { + pidfile_remove(pfh); + err(1, "failed to initialize kqueue"); + } + for (int i = 0; i < (int)nitems(sigcatch); ++i) { + EV_SET(&ev, sigcatch[i], EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { + pidfile_remove(pfh); + err(1, "failed to add kevent to kqueue"); + } + (void)sigaddset(&sigset, sigcatch[i]); + } + (void)sigdelset(&sigset, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &sigset, NULL) != 0) { + pidfile_remove(pfh); + err(1, "failed to apply signal mask"); + } + (void)alarm(TIMERINTVL); /* tuck my process id away */ @@ -790,94 +792,57 @@ dprintf("off & running....\n"); - tvp = &tv; - tv.tv_sec = tv.tv_usec = 0; - STAILQ_FOREACH(sl, &shead, next) { - if (sl->sl_socket > fdsrmax) - fdsrmax = sl->sl_socket; + EV_SET(&ev, sl->sl_socket, EVFILT_READ, EV_ADD | EV_CLEAR, + 0, 0, sl); + if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { + pidfile_remove(pfh); + err(1, "failed to add kevent to kqueue"); + } } - fdsr = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS), - sizeof(*fdsr)); - if (fdsr == NULL) - errx(1, "calloc fd_set"); + init(false); for (;;) { - if (!Initialized) - init(0); - else if (WantInitialize) - init(WantInitialize); - if (WantReapchild) - reapchild(WantReapchild); - if (MarkSet) - markit(); - if (WantDie) { - free(fdsr); - die(WantDie); - } - - bzero(fdsr, howmany(fdsrmax+1, NFDBITS) * - sizeof(*fdsr)); - - STAILQ_FOREACH(sl, &shead, next) { - if (sl->sl_socket != -1 && sl->sl_recv != NULL) - FD_SET(sl->sl_socket, fdsr); - } - i = select(fdsrmax + 1, fdsr, NULL, NULL, - needdofsync ? &tv : tvp); - switch (i) { + switch (kevent(kq, NULL, 0, &ev, 1, needdofsync ? &ts : tsp)) { case 0: dofsync(); - needdofsync = false; - if (tvp) { - tvp = NULL; - if (ppid != 1) + if (tsp != NULL) { + tsp = NULL; + if (ppid != -1) kill(ppid, SIGALRM); } continue; case -1: if (errno != EINTR) - logerror("select"); + logerror("kevent"); continue; } - STAILQ_FOREACH(sl, &shead, next) { - if (FD_ISSET(sl->sl_socket, fdsr)) - (*sl->sl_recv)(sl); - } - } - free(fdsr); -} - -static int -socklist_recv_signal(struct socklist *sl __unused) -{ - ssize_t len; - int i, nsig, signo; - - if (ioctl(sigpipe[0], FIONREAD, &i) != 0) { - logerror("ioctl(FIONREAD)"); - err(1, "signal pipe read failed"); - } - nsig = i / sizeof(signo); - dprintf("# of received signals = %d\n", nsig); - for (i = 0; i < nsig; i++) { - len = read(sigpipe[0], &signo, sizeof(signo)); - if (len != sizeof(signo)) { - logerror("signal pipe read failed"); - err(1, "signal pipe read failed"); - } - dprintf("Received signal: %d from fd=%d\n", signo, - sigpipe[0]); - switch (signo) { - case SIGHUP: - WantInitialize = 1; - break; - case SIGCHLD: - WantReapchild = 1; - break; + switch (ev.filter) { + case EVFILT_READ: + sl = ev.udata; + if (sl->sl_socket != -1 && sl->sl_recv != NULL) + sl->sl_recv(sl); + continue; + case EVFILT_SIGNAL: + switch (ev.ident) { + case SIGHUP: + init(true); + break; + case SIGCHLD: + reapchild(); + break; + case SIGINT: + case SIGQUIT: + case SIGTERM: + if (ev.ident == SIGTERM || Debug) + die(ev.ident); + break; + case SIGALRM: + markit(); + break; + } } } - return (0); } static int @@ -1767,6 +1732,7 @@ (void)fsync(f->f_file); } } + needdofsync = false; } /* @@ -2240,7 +2206,7 @@ } static void -reapchild(int signo __unused) +reapchild(void) { int status; pid_t pid; @@ -2261,7 +2227,6 @@ } } } - WantReapchild = 0; } /* @@ -2300,20 +2265,6 @@ return (hname); } -static void -dodie(int signo) -{ - - WantDie = signo; -} - -static void -domark(int signo __unused) -{ - - MarkSet = 1; -} - /* * Print syslogd errors some place. */ @@ -2539,19 +2490,11 @@ } } -static void -sighandler(int signo) -{ - - /* Send an wake-up signal to the select() loop. */ - write(sigpipe[1], &signo, sizeof(signo)); -} - /* * INIT -- Initialize syslogd from configuration table */ static void -init(int signo) +init(bool reload) { int i; struct filed *f; @@ -2561,12 +2504,11 @@ char bootfileMsg[MAXLINE + 1]; dprintf("init\n"); - WantInitialize = 0; /* * Load hostname (may have changed). */ - if (signo != 0) + if (reload) (void)strlcpy(oldLocalHostName, LocalHostName, sizeof(oldLocalHostName)); if (gethostname(LocalHostName, sizeof(LocalHostName))) @@ -2706,9 +2648,9 @@ NULL, NULL, "restart", 0); dprintf("syslogd: restarted\n"); /* - * Log a change in hostname, but only on a restart. + * Log a change in hostname, but only on reload. */ - if (signo != 0 && strcmp(oldLocalHostName, LocalHostName) != 0) { + if (reload && strcmp(oldLocalHostName, LocalHostName) != 0) { (void)snprintf(hostMsg, sizeof(hostMsg), "hostname changed, \"%s\" to \"%s\"", oldLocalHostName, LocalHostName); @@ -2718,9 +2660,9 @@ } /* * Log the kernel boot file if we aren't going to use it as - * the prefix, and if this is *not* a restart. + * the prefix, and if this is *not* a reload. */ - if (signo == 0 && !use_bootfile) { + if (!reload && !use_bootfile) { (void)snprintf(bootfileMsg, sizeof(bootfileMsg), "kernel boot file is %s", bootfile); logmsg(LOG_KERN | LOG_INFO, NULL, LocalHostName, "syslogd", @@ -3244,7 +3186,6 @@ dq->dq_timeout--; } } - MarkSet = 0; (void)alarm(TIMERINTVL); } @@ -3592,6 +3533,7 @@ { int pfd[2], nulldesc; pid_t pid; + sigset_t sigset = { }; char *argv[4]; /* sh -c cmd NULL */ char errmsg[200]; @@ -3619,10 +3561,12 @@ alarm(0); - /* Restore signals marked as SIG_IGN. */ - (void)signal(SIGINT, SIG_DFL); - (void)signal(SIGQUIT, SIG_DFL); - (void)signal(SIGPIPE, SIG_DFL); + for (int i = 0; i < (int)nitems(sigcatch); ++i) + (void)sigaddset(&sigset, sigcatch[i]); + if (sigprocmask(SIG_UNBLOCK, &sigset, NULL) != 0) { + logerror("sigprocmask"); + exit(1); + } dup2(pfd[0], STDIN_FILENO); dup2(nulldesc, STDOUT_FILENO);