File pacemaker-lrmd-pacemaker-remote-reap-zombies.patch of Package pacemaker.14737
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);