From cdf67f33be48a1f68351fef8eafe0c22838c2f02 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Mon, 7 Jan 2013 21:59:32 +0100 Subject: [PATCH] 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. --- src/daemon/priv.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) 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 */ -- 2.39.5