]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Don't wait for the process to finish when stopping it
authorRoy Marples <roy@marples.name>
Thu, 4 Jun 2020 11:15:20 +0000 (12:15 +0100)
committerRoy Marples <roy@marples.name>
Thu, 4 Jun 2020 11:15:20 +0000 (12:15 +0100)
Instead, wait on receipt of SIGCHLD so we're not blocked.

src/dhcpcd.c
src/privsep-root.c
src/privsep.c

index 0c759ca37e168d6bf1c545f71a54f92a01accdcd..1363b3c7f379af231e747495f3b6d5bc1415f4de 100644 (file)
@@ -87,6 +87,7 @@ const int dhcpcd_signals[] = {
        SIGHUP,
        SIGUSR1,
        SIGUSR2,
+       SIGCHLD,
 };
 const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals);
 
@@ -1399,7 +1400,7 @@ dhcpcd_signal_cb(int sig, void *arg)
        unsigned long long opts;
        int exit_code;
 
-       if (ctx->options & DHCPCD_FORKED) {
+       if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) {
                pid_t pid = pidfile_read(ctx->pidfile);
                if (pid == -1) {
                        if (errno != ENOENT)
@@ -1445,6 +1446,10 @@ dhcpcd_signal_cb(int sig, void *arg)
                if (logopen(ctx->logfile) == -1)
                        logerr(__func__);
                return;
+       case SIGCHLD:
+               while (waitpid(-1, NULL, WNOHANG) > 0)
+                       ;
+               return;
        default:
                logerrx("received signal %d but don't know what to do with it",
                    sig);
@@ -2215,7 +2220,6 @@ printpidfile:
                }
                break;
        default:
-               waitpid(pid, &i, 0);
                ctx.options |= DHCPCD_FORKED; /* A lie */
                ctx.fork_fd = sigpipe[0];
                close(sigpipe[1]);
index 5c91b4a82b1fe9598642203f12f3daff5826dd48..2a45abb9092cd94c9d525c4f9fe3c8087e219d56 100644 (file)
@@ -686,6 +686,13 @@ ps_root_signalcb(int sig, void *arg)
        if (sig == SIGINT)
                return;
 
+       /* Reap children */
+       if (sig == SIGCHLD) {
+               while (waitpid(-1, NULL, WNOHANG) > 0)
+                       ;
+               return;
+       }
+
        logerrx("process %d unexpectedly terminating on signal %d",
            getpid(), sig);
        if (ctx->ps_root_pid == getpid()) {
index 5d7e2ca5eae3481b870912272b7e396b4ccdb54c..e2f3f3cde3ab20991eebbd4d0e7449fa4c78105d 100644 (file)
@@ -291,61 +291,28 @@ errexit:
 int
 ps_dostop(struct dhcpcd_ctx *ctx, pid_t *pid, int *fd)
 {
-       int status;
+       int err = 0;
 
 #ifdef PRIVSEP_DEBUG
        logdebugx("%s: pid %d fd %d", __func__, *pid, *fd);
 #endif
-       if (*pid == 0)
-               return 0;
-       if (*fd == -1)
-               goto wait;
-
-       eloop_event_delete(ctx->eloop, *fd);
-       if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1 &&
-           errno != ECONNRESET)
-               logerr(__func__);
-       if (shutdown(*fd, SHUT_RDWR) == -1 && errno != ENOTCONN)
-               logerr(__func__);
-       close(*fd);
-       *fd = -1;
-
-wait:
-       status = 0;
 
-#ifdef HAVE_CAPSICUM
-       unsigned int cap_mode = 0;
-       int cap_err = cap_getmode(&cap_mode);
-
-       if (cap_err == -1) {
-               if (errno != ENOSYS)
-                       logerr("%s: cap_getmode", __func__);
-       } else if (cap_mode != 0)
-               goto nowait;
-#endif
-
-       /* Wait for the process to finish */
-       while (waitpid(*pid, &status, 0) == -1) {
-               if (errno != EINTR) {
-                       logerr("%s: waitpid", __func__);
-                       status = 0;
-                       break;
+       if (*fd != -1) {
+               eloop_event_delete(ctx->eloop, *fd);
+               if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1 ||
+                   shutdown(*fd, SHUT_RDWR) == -1)
+               {
+                       logerr(__func__);
+                       err = -1;
                }
-#ifdef PRIVSEP_DEBUG
-               else
-                       logerr("%s: waitpid ", __func__);
-#endif
+               close(*fd);
+               *fd = -1;
        }
-#ifdef HAVE_CAPSICUM
-nowait:
-#endif
-       *pid = 0;
 
-#ifdef PRIVSEP_DEBUG
-       logdebugx("%s: status %d", __func__, status);
-#endif
-
-       return status;
+       /* Don't wait for the process as it may not respond to the shutdown
+        * request. We'll reap the process on receipt of SIGCHLD. */
+       *pid = 0;
+       return err;
 }
 
 int