From: Vincent Bernat Date: Mon, 7 Jan 2013 20:59:32 +0000 (+0100) Subject: priv: mirror the exit status of the child X-Git-Tag: 0.7.1~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cdf67f33be48a1f68351fef8eafe0c22838c2f02;p=thirdparty%2Flldpd.git priv: mirror the exit status of the child When exiting because the child has exited, the privileged processus will mirror the exit status and the signal that killed the child if any. This allows monitoring daemon like systemd to detect an unexpected exit. --- diff --git a/src/daemon/priv.c b/src/daemon/priv.c index 67612b86..5f30ef91 100644 --- a/src/daemon/priv.c +++ b/src/daemon/priv.c @@ -494,13 +494,37 @@ static void priv_exit() { int status; - if (waitpid(monitored, &status, WNOHANG) == 0) { + int rc; + rc = waitpid(monitored, &status, WNOHANG); + switch (rc) { + case 0: log_debug("privsep", "killing child"); kill(monitored, SIGTERM); + log_debug("privsep", "waiting for child %d to terminate", monitored); + return; + case -1: + log_debug("privsep", "child does not exist anymore"); + _exit(1); /* We consider this is an error to be here */ + break; + default: + log_debug("privsep", "monitored child has terminated"); + /* Mimic the exit state of the child */ + if (WIFEXITED(status)) { + log_debug("privsep", "monitored child has terminated with status %d", + WEXITSTATUS(status)); + _exit(WEXITSTATUS(status)); + } + if (WIFSIGNALED(status)) { + log_debug("privsep", "monitored child has terminated with signal %d", + WTERMSIG(status)); + signal(WTERMSIG(status), SIG_DFL); + raise(WTERMSIG(status)); + _exit(1); /* We consider that not being killed is an error. */ + } + /* Other cases, consider this as an error. */ + _exit(1); + break; } - if (waitpid(monitored, &status, WNOHANG) == -1) - _exit(0); - log_debug("privsep", "waiting for child %d to terminate", monitored); } /* If priv parent gets a TERM or HUP, pass it through to child instead */