The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8536447a07fa29073f93af70808db58c760aa6f9

commit 8536447a07fa29073f93af70808db58c760aa6f9
Author:     Jake Freeland <jf...@freebsd.org>
AuthorDate: 2023-09-01 02:51:28 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2023-09-28 15:51:54 +0000

    syslogd: Use pipe to communicate with daemon
    
    Previously, syslogd's daemon process would signal that it had finished
    initialization using SIGALRM. In capability mode, signal delivery is not
    allowed, so use a pipe to indicate that it is ready to accept messages.
    
    Reviewed by:    markj
    MFC after:      3 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D41459
---
 usr.sbin/syslogd/syslogd.c | 100 ++++++++++++++++++++-------------------------
 1 file changed, 44 insertions(+), 56 deletions(-)

diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index 3f9633ca8c35..8d2f3c3edf14 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -135,6 +135,7 @@ static char sccsid[] = "@(#)syslogd.c       8.3 (Berkeley) 
4/4/94";
 #include <limits.h>
 #include <netdb.h>
 #include <paths.h>
+#include <poll.h>
 #include <regex.h>
 #include <signal.h>
 #include <stdbool.h>
@@ -471,7 +472,6 @@ static bool validate(struct sockaddr *, const char *);
 static void    unmapped(struct sockaddr *);
 static void    wallmsg(struct filed *, struct iovec *, const int iovlen);
 static int     waitdaemon(int);
-static void    timedout(int);
 static void    increase_rcvbuf(int);
 
 static void
@@ -599,8 +599,8 @@ main(int argc, char *argv[])
        struct sigaction act = { };
        struct kevent ev;
        struct socklist *sl;
-       pid_t ppid = -1, spid;
-       int ch, kq, s;
+       pid_t spid;
+       int ch, kq, ppipe_w = -1, s;
        char *p;
        bool bflag = false, pflag = false, Sflag = false;
 
@@ -813,14 +813,9 @@ main(int argc, char *argv[])
 
        (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile));
 
-       if ((!Foreground) && (!Debug)) {
-               ppid = waitdaemon(30);
-               if (ppid < 0) {
-                       warn("could not become daemon");
-                       pidfile_remove(pfh);
-                       exit(1);
-               }
-       } else if (Debug)
+       if (!Foreground && !Debug)
+               ppipe_w = waitdaemon(30);
+       else if (Debug)
                setlinebuf(stdout);
 
        kq = kqueue();
@@ -868,9 +863,14 @@ main(int argc, char *argv[])
        for (;;) {
                if (needdofsync) {
                        dofsync();
-                       if (ppid != -1) {
-                               kill(ppid, SIGALRM);
-                               ppid = -1;
+                       if (ppipe_w != -1) {
+                               /*
+                                * Close our end of the pipe so our
+                                * parent knows that we have finished
+                                * initialization.
+                                */
+                               (void)close(ppipe_w);
+                               ppipe_w = -1;
                        }
                }
                if (kevent(kq, NULL, 0, &ev, 1, NULL) == -1) {
@@ -3237,64 +3237,52 @@ markit(void)
 /*
  * fork off and become a daemon, but wait for the child to come online
  * before returning to the parent, or we get disk thrashing at boot etc.
- * Set a timer so we don't hang forever if it wedges.
  */
 static int
 waitdaemon(int maxwait)
 {
-       int status;
-       pid_t pid, childpid;
+       struct pollfd pollfd;
+       int events, pipefd[2], status;
+       pid_t pid;
 
-       switch (childpid = fork()) {
-       case -1:
-               return (-1);
-       case 0:
-               break;
-       default:
-               signal(SIGALRM, timedout);
-               alarm(maxwait);
-               while ((pid = wait3(&status, 0, NULL)) != -1) {
+       if (pipe(pipefd) == -1) {
+               warn("failed to daemonize, pipe");
+               die(0);
+       }
+       pid = fork();
+       if (pid == -1) {
+               warn("failed to daemonize, fork");
+               die(0);
+       } else if (pid > 0) {
+               close(pipefd[1]);
+               pollfd.fd = pipefd[0];
+               pollfd.events = POLLHUP;
+               events = poll(&pollfd, 1, maxwait * 1000);
+               if (events == -1)
+                       err(1, "failed to daemonize, poll");
+               else if (events == 0)
+                       errx(1, "timed out waiting for child");
+               if (waitpid(pid, &status, WNOHANG) > 0) {
                        if (WIFEXITED(status))
                                errx(1, "child pid %d exited with return code 
%d",
-                                       pid, WEXITSTATUS(status));
+                                   pid, WEXITSTATUS(status));
                        if (WIFSIGNALED(status))
                                errx(1, "child pid %d exited on signal %d%s",
-                                       pid, WTERMSIG(status),
-                                       WCOREDUMP(status) ? " (core dumped)" :
-                                       "");
-                       if (pid == childpid)    /* it's gone... */
-                               break;
+                                   pid, WTERMSIG(status),
+                                   WCOREDUMP(status) ? " (core dumped)" : "");
                }
                exit(0);
        }
-
-       if (setsid() == -1)
-               return (-1);
-
+       close(pipefd[0]);
+       if (setsid() == -1) {
+               warn("failed to daemonize, setsid");
+               die(0);
+       }
        (void)chdir("/");
        (void)dup2(nulldesc, STDIN_FILENO);
        (void)dup2(nulldesc, STDOUT_FILENO);
        (void)dup2(nulldesc, STDERR_FILENO);
-       return (getppid());
-}
-
-/*
- * We get a SIGALRM from the child when it's running and finished doing it's
- * fsync()'s or O_SYNC writes for all the boot messages.
- *
- * We also get a signal from the kernel if the timer expires, so check to
- * see what happened.
- */
-static void
-timedout(int sig __unused)
-{
-       int left;
-       left = alarm(0);
-       signal(SIGALRM, SIG_DFL);
-       if (left == 0)
-               errx(1, "timed out waiting for child");
-       else
-               _exit(0);
+       return (pipefd[1]);
 }
 
 /*

Reply via email to