commit 8abdd82ba85ee384ab78ce1db617f51b692e9df6
Author: Andrew Beekhof <andrew@beekhof.net>
Date:   Wed Apr 19 12:55:08 2017 +1000

    lrmd: Have pacemaker-remote reap zombies if it is running as pid 1

diff --git a/configure.ac b/configure.ac
index ee98f9bf3..5e08e7b28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -823,6 +823,16 @@ if test "$ac_cv_header_libxslt_xslt_h" != "yes"; then
    AC_MSG_ERROR(The libxslt developement headers were not found)
 fi
 
+AC_CACHE_CHECK(whether __progname and __progname_full are available,
+                pf_cv_var_progname,
+                AC_TRY_LINK([extern char *__progname, *__progname_full;],
+                    [__progname = "foo"; __progname_full = "foo bar";],
+                    pf_cv_var_progname="yes", pf_cv_var_progname="no"))
+
+if test "$pf_cv_var_progname" = "yes"; then
+    AC_DEFINE(HAVE___PROGNAME,1,[ ])
+fi
+
 dnl ========================================================================
 dnl Structures
 dnl ========================================================================
diff --git a/lrmd/main.c b/lrmd/main.c
index ca8cdf2c5..412ce2490 100644
--- a/lrmd/main.c
+++ b/lrmd/main.c
@@ -21,6 +21,11 @@
 
 #include <glib.h>
 #include <unistd.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
 
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
@@ -391,6 +396,119 @@ void handle_shutdown_nack()
     crm_debug("Ignoring unexpected shutdown nack");
 }
 
+
+static pid_t main_pid = 0;
+static void
+sigdone(void)
+{
+    exit(0);
+}
+
+static void
+sigreap(void)
+{
+    pid_t pid = 0;
+    int status;
+    do {
+        /*
+         * Opinions seem to differ as to what to put here:
+         *  -1, any child process
+         *  0,  any child process whose process group ID is equal to that of the calling process
+         */
+        pid = waitpid(-1, &status, WNOHANG);
+        if(pid == main_pid) {
+            /* Exit when pacemaker-remote exits and use the same return code */
+            if (WIFEXITED(status)) {
+                exit(WEXITSTATUS(status));
+            }
+            exit(1);
+        }
+
+    } while (pid > 0);
+}
+
+static struct {
+	int sig;
+	void (*handler)(void);
+} sigmap[] = {
+	{ SIGCHLD, sigreap },
+	{ SIGINT,  sigdone },
+};
+
+static void spawn_pidone(int argc, char **argv, char **envp)
+{
+    sigset_t set;
+
+    if (getpid() != 1) {
+        return;
+    }
+
+    sigfillset(&set);
+    sigprocmask(SIG_BLOCK, &set, 0);
+
+    main_pid = fork();
+    switch (main_pid) {
+	case 0:
+            sigprocmask(SIG_UNBLOCK, &set, NULL);
+            setsid();
+            setpgid(0, 0);
+
+            /* Child remains as pacemaker_remoted */
+            return;
+	case -1:
+            perror("fork");
+    }
+
+    /* Parent becomes the reaper of zombie processes */
+    /* Safe to initialize logging now if needed */
+
+#ifdef HAVE___PROGNAME
+    /* Differentiate ourselves in the 'ps' output */
+    {
+        char *p;
+        int i, maxlen;
+        char *LastArgv = NULL;
+        const char *name = "pcmk-init";
+
+	for(i = 0; i < argc; i++) {
+		if(!i || (LastArgv + 1 == argv[i]))
+			LastArgv = argv[i] + strlen(argv[i]);
+	}
+
+	for(i = 0; envp[i] != NULL; i++) {
+		if((LastArgv + 1) == envp[i]) {
+			LastArgv = envp[i] + strlen(envp[i]);
+		}
+	}
+
+        maxlen = (LastArgv - argv[0]) - 2;
+
+        i = strlen(name);
+        /* We can overwrite individual argv[] arguments */
+        snprintf(argv[0], maxlen, "%s", name);
+
+        /* Now zero out everything else */
+        p = &argv[0][i];
+        while(p < LastArgv)
+            *p++ = '\0';
+        argv[1] = NULL;
+    }
+#endif /* HAVE___PROGNAME */
+
+    while (1) {
+	int sig;
+	size_t i;
+
+        sigwait(&set, &sig);
+        for (i = 0; i < DIMOF(sigmap); i++) {
+            if (sigmap[i].sig == sig) {
+                sigmap[i].handler();
+                break;
+            }
+        }
+    }
+}
+
 /* *INDENT-OFF* */
 static struct crm_option long_options[] = {
     /* Top-level Options */
@@ -410,12 +528,14 @@ static struct crm_option long_options[] = {
 /* *INDENT-ON* */
 
 int
-main(int argc, char **argv)
+main(int argc, char **argv, char **envp)
 {
     int flag = 0;
     int index = 0;
     const char *option = NULL;
 
+    /* If necessary, create PID1 now before any FDs are opened */
+    spawn_pidone(argc, argv, envp);
 
 #ifndef ENABLE_PCMK_REMOTE
     crm_log_preinit("lrmd", argc, argv);
