From: Roy Marples Date: Thu, 4 Jun 2020 11:15:20 +0000 (+0100) Subject: privsep: Don't wait for the process to finish when stopping it X-Git-Tag: v9.1.1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d006faa0a2d70427e98794eaff310e85c482ed2;p=thirdparty%2Fdhcpcd.git privsep: Don't wait for the process to finish when stopping it Instead, wait on receipt of SIGCHLD so we're not blocked. --- diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 0c759ca3..1363b3c7 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -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]); diff --git a/src/privsep-root.c b/src/privsep-root.c index 5c91b4a8..2a45abb9 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -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()) { diff --git a/src/privsep.c b/src/privsep.c index 5d7e2ca5..e2f3f3cd 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -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