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 @@ -109,6 +109,7 @@ #include #include #include +#include #include #include #include @@ -321,7 +322,7 @@ } f_forw; /* F_FORW */ struct { char f_pname[MAXPATHLEN]; - pid_t f_pid; + int f_procdesc; } f_pipe; /* F_PIPE */ } f_un; #define fu_uname f_un.f_uname @@ -329,7 +330,7 @@ #define fu_forw_hname f_un.f_forw.f_hname #define fu_forw_addr f_un.f_forw.f_addr #define fu_pipe_pname f_un.f_pipe.f_pname -#define fu_pipe_pid f_un.f_pipe.f_pid +#define fu_pipe_pd f_un.f_pipe.f_procdesc /* Book-keeping. */ char f_prevline[MAXSVLINE]; /* last message logged */ @@ -350,7 +351,7 @@ * Queue of about-to-be dead processes we should watch out for. */ struct deadq_entry { - pid_t dq_pid; + int dq_procdesc; int dq_timeout; TAILQ_ENTRY(deadq_entry) dq_entries; }; @@ -420,9 +421,8 @@ static void addsock(const char *, const char *, mode_t); static void cfline(const char *, const char *, const char *, const char *); static const char *cvthname(struct sockaddr *); -static void deadq_enter(pid_t, const char *); -static int deadq_remove(struct deadq_entry *); -static int deadq_removebypid(pid_t); +static void deadq_enter(int); +static void deadq_remove(struct deadq_entry *); static int decode(const char *, const CODE *); static void die(int) __dead2; static void dofsync(void); @@ -447,7 +447,7 @@ static void parsemsg(const char *, char *); static void printsys(char *); static int p_open(const char *, pid_t *); -static void reapchild(void); +static void reapchild(int); static const char *ttymsg_check(struct iovec *, int, char *, int); static void usage(void); static bool validate(struct sockaddr *, const char *); @@ -477,7 +477,10 @@ f->f_type = F_UNUSED; break; case F_PIPE: - f->fu_pipe_pid = 0; + if (f->fu_pipe_pd != -1) { + (void)close(f->fu_pipe_pd); + f->fu_pipe_pd = -1; + } break; default: break; @@ -940,9 +943,6 @@ case SIGHUP: init(true); break; - case SIGCHLD: - reapchild(); - break; case SIGINT: case SIGQUIT: case SIGTERM: @@ -953,7 +953,13 @@ markit(); break; } + continue; + case EVFILT_PROCDESC: + if ((ev.fflags & NOTE_EXIT) != 0) + reapchild(ev.ident); + continue; } + } } @@ -2005,17 +2011,16 @@ case F_PIPE: dprintf(" %s\n", f->fu_pipe_pname); iovlist_append(il, "\n"); - if (f->fu_pipe_pid == 0) { + if (f->fu_pipe_pd == -1) { if ((f->f_file = p_open(f->fu_pipe_pname, - &f->fu_pipe_pid)) < 0) { + &f->fu_pipe_pd)) < 0) { logerror(f->fu_pipe_pname); break; } } if (writev(f->f_file, il->iov, il->iovcnt) < 0) { int e = errno; - - deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname); + deadq_enter(f->fu_pipe_pd); close_filed(f); errno = e; logerror(f->fu_pipe_pname); @@ -2318,25 +2323,24 @@ } static void -reapchild(void) +reapchild(int pd) { - int status; - pid_t pid; struct filed *f; + pid_t pid; + int status; - while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) { - /* First, look if it's a process from the dead queue. */ - if (deadq_removebypid(pid)) - continue; + if (pd == -1) + return; - /* Now, look in list of active processes. */ - STAILQ_FOREACH(f, &fhead, next) { - if (f->f_type == F_PIPE && - f->fu_pipe_pid == pid) { - close_filed(f); - log_deadchild(pid, status, f->fu_pipe_pname); - break; - } + /* Now, look in list of active processes. */ + STAILQ_FOREACH(f, &fhead, next) { + if (f->f_type == F_PIPE && f->fu_pipe_pd == pd) { + (void)pdgetpid(pd, &pid); + if (waitpid(pid, &status, 0) != pid) + logerror("waitpid"); + close_filed(f); + log_deadchild(pid, status, f->fu_pipe_pname); + break; } } } @@ -2413,7 +2417,7 @@ /* flush any pending output */ if (f->f_prevcount) fprintlog_successive(f, 0); - if (f->f_type == F_PIPE && f->fu_pipe_pid > 0) + if (f->f_type == F_PIPE && f->fu_pipe_pd >= 0) close_filed(f); } if (signo) { @@ -2670,7 +2674,7 @@ close_filed(f); break; case F_PIPE: - deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname); + deadq_enter(f->fu_pipe_pd); close_filed(f); break; default: @@ -3193,7 +3197,7 @@ break; case '|': - f->fu_pipe_pid = 0; + f->fu_pipe_pd = -1; (void)strlcpy(f->fu_pipe_pname, p + 1, sizeof(f->fu_pipe_pname)); f->f_type = F_PIPE; @@ -3278,7 +3282,7 @@ switch (dq->dq_timeout) { case 0: /* Already signalled once, try harder now. */ - if (kill(dq->dq_pid, SIGKILL) != 0) + if (pdkill(dq->dq_procdesc, SIGKILL) != 0) (void)deadq_remove(dq); break; @@ -3291,7 +3295,7 @@ * didn't even really exist, in case we simply * drop it from the dead queue). */ - if (kill(dq->dq_pid, SIGTERM) != 0) + if (pdkill(dq->dq_procdesc, SIGTERM) != 0) (void)deadq_remove(dq); else dq->dq_timeout--; @@ -3638,9 +3642,9 @@ * opposed to a FILE *. */ static int -p_open(const char *prog, pid_t *rpid) +p_open(const char *prog, int *rpd) { - int pfd[2], nulldesc; + int nulldesc, pfd[2], pd; pid_t pid; sigset_t sigset = { }; char *argv[4]; /* sh -c cmd NULL */ @@ -3652,7 +3656,7 @@ /* we are royally screwed anyway */ return (-1); - switch ((pid = fork())) { + switch ((pid = pdfork(&pd, PD_CLOEXEC))) { case -1: close(nulldesc); return (-1); @@ -3704,63 +3708,36 @@ (int)pid); logerror(errmsg); } - *rpid = pid; + *rpd = pd; return (pfd[1]); } static void -deadq_enter(pid_t pid, const char *name) +deadq_enter(int pd) { struct deadq_entry *dq; - int status; - if (pid == 0) + if (pd == -1) return; - /* - * Be paranoid, if we can't signal the process, don't enter it - * into the dead queue (perhaps it's already dead). If possible, - * we try to fetch and log the child's status. - */ - if (kill(pid, 0) != 0) { - if (waitpid(pid, &status, WNOHANG) > 0) - log_deadchild(pid, status, name); - return; - } dq = malloc(sizeof(*dq)); if (dq == NULL) { logerror("malloc"); exit(1); } - *dq = (struct deadq_entry){ - .dq_pid = pid, - .dq_timeout = DQ_TIMO_INIT - }; + + dq->dq_procdesc = pd; + dq->dq_timeout = DQ_TIMO_INIT; TAILQ_INSERT_TAIL(&deadq_head, dq, dq_entries); } -static int +static void deadq_remove(struct deadq_entry *dq) { if (dq != NULL) { TAILQ_REMOVE(&deadq_head, dq, dq_entries); free(dq); - return (1); - } - - return (0); -} - -static int -deadq_removebypid(pid_t pid) -{ - struct deadq_entry *dq; - - TAILQ_FOREACH(dq, &deadq_head, dq_entries) { - if (dq->dq_pid == pid) - break; } - return (deadq_remove(dq)); } static void