]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
priv: mirror the exit status of the child
authorVincent Bernat <bernat@luffy.cx>
Mon, 7 Jan 2013 20:59:32 +0000 (21:59 +0100)
committerVincent Bernat <bernat@luffy.cx>
Mon, 7 Jan 2013 20:59:32 +0000 (21:59 +0100)
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

index 67612b86a054f857809af2ccd200dc87cdaffe0c..5f30ef91dfd4ec0af81cd510947555f30ded60ec 100644 (file)
@@ -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 */