-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 08/06/2009 05:13 PM, Jakub Hrozek wrote:
> We could catch most signals the way we do catch SIGTERM and relay them
> to children. This still wouldn't cover the SIGKILL case where the admin
> shoots down monitor. This is cross-platform which is of course huge
> advantage.
> 
> But in my opinion, we should still use prctl() where available, because
> it is much cleaner solution -- you don't have to explicitly enumerate
> all the signals to handle and you can also cover the SIGKILL case.
> 

Attached is a patch that says the same in C.

        Jakub
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAkqBg9AACgkQHsardTLnvCVgbACgiRfGHqtEXzTKw1VO1rk15PJp
RYIAoI7c/zqImOxM5g9GgBlRfmF+m+UN
=2z7H
-----END PGP SIGNATURE-----
>From ff1abebe6a7d6ab6660aa14ea9708cc2a3457baf Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Mon, 3 Aug 2009 11:55:36 +0200
Subject: [PATCH] Make child processes exit when parent dies

The child processes call prctl() and when their parent process is
killed, they are sent SIGTERM using prctl. This is currently
Linux-specific, for non-Linuxes, a similar effect is achieved by
catching a set of common termination signals and sending SIGTERM to the
process group.
---
 server/providers/data_provider.c    |    6 ++++
 server/providers/data_provider_be.c |    6 ++++
 server/responder/nss/nsssrv.c       |    6 ++++
 server/responder/pam/pamsrv.c       |    6 ++++
 server/util/server.c                |   44 +++++++++++++++++++++++++++++++++++
 server/util/signal.m4               |    2 +-
 server/util/util.h                  |    1 +
 7 files changed, 70 insertions(+), 1 deletions(-)

diff --git a/server/providers/data_provider.c b/server/providers/data_provider.c
index b952925..f0ecd30 100644
--- a/server/providers/data_provider.c
+++ b/server/providers/data_provider.c
@@ -1088,6 +1088,12 @@ int main(int argc, const char *argv[])
     ret = server_setup("sssd[dp]", 0, DP_CONF_ENTRY, &main_ctx);
     if (ret != EOK) return 2;
 
+    ret = die_if_parent_died();
+    if (ret != EOK) {
+        /* This is not fatal, don't return */
+        DEBUG(2, ("Could not set up to exit when parent process does\n"));
+    }
+
     ret = dp_process_init(main_ctx,
                            main_ctx->event_ctx,
                            main_ctx->confdb_ctx);
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
index 872c9d7..7e2599a 100644
--- a/server/providers/data_provider_be.c
+++ b/server/providers/data_provider_be.c
@@ -1110,6 +1110,12 @@ int main(int argc, const char *argv[])
         return 2;
     }
 
+    ret = die_if_parent_died();
+    if (ret != EOK) {
+        /* This is not fatal, don't return */
+        DEBUG(2, ("Could not set up to exit when parent process does\n"));
+    }
+
     ret = be_process_init(main_ctx,
                           be_name, be_domain,
                           main_ctx->event_ctx,
diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c
index 248d538..418e2f9 100644
--- a/server/responder/nss/nsssrv.c
+++ b/server/responder/nss/nsssrv.c
@@ -365,6 +365,12 @@ int main(int argc, const char *argv[])
     ret = server_setup("sssd[nss]", 0, NSS_SRV_CONFIG, &main_ctx);
     if (ret != EOK) return 2;
 
+    ret = die_if_parent_died();
+    if (ret != EOK) {
+        /* This is not fatal, don't return */
+        DEBUG(2, ("Could not set up to exit when parent process does\n"));
+    }
+
     ret = nss_process_init(main_ctx,
                            main_ctx->event_ctx,
                            main_ctx->confdb_ctx);
diff --git a/server/responder/pam/pamsrv.c b/server/responder/pam/pamsrv.c
index 48286ec..f540a3c 100644
--- a/server/responder/pam/pamsrv.c
+++ b/server/responder/pam/pamsrv.c
@@ -228,6 +228,12 @@ int main(int argc, const char *argv[])
     ret = server_setup("sssd[pam]", 0, PAM_SRV_CONFIG, &main_ctx);
     if (ret != EOK) return 2;
 
+    ret = die_if_parent_died();
+    if (ret != EOK) {
+        /* This is not fatal, don't return */
+        DEBUG(2, ("Could not set up to exit when parent process does\n"));
+    }
+
     pam_dp_interface = get_pam_dp_interface();
     sss_cmds = register_sss_cmds();
     ret = sss_process_init(main_ctx,
diff --git a/server/util/server.c b/server/util/server.c
index fd6e4cd..d20a823 100644
--- a/server/util/server.c
+++ b/server/util/server.c
@@ -33,6 +33,10 @@
 #include "ldb.h"
 #include "confdb/confdb.h"
 
+#ifdef HAVE_PRCTL
+#include <sys/prctl.h>
+#endif
+
 /*******************************************************************
  Close the low 3 fd's and open dev/null in their place.
 ********************************************************************/
@@ -191,6 +195,21 @@ static void sig_term(int sig)
 	exit(0);
 }
 
+#ifndef HAVE_PRCTL
+static void sig_segv_abrt(int sig)
+{
+#if HAVE_GETPGRP
+	static int done;
+	if (done == 0 && getpgrp() == getpid()) {
+		DEBUG(0,("%s: killing children\n", strsignal(sig)));
+		done = 1;
+		kill(-getpgrp(), SIGTERM);
+	}
+#endif  /* HAVE_GETPGRP */
+    exit(1);
+}
+#endif /* HAVE_PRCTL */
+
 /*
   setup signal masks
 */
@@ -219,6 +238,14 @@ static void setup_signals(void)
 
 	CatchSignal(SIGHUP, sig_hup);
 	CatchSignal(SIGTERM, sig_term);
+
+#ifndef HAVE_PRCTL
+        /* If prctl is not defined on the system, try to handle
+         * some common termination signals gracefully */
+	CatchSignal(SIGSEGV, sig_segv_abrt);
+	CatchSignal(SIGABRT, sig_segv_abrt);
+#endif
+
 }
 
 /*
@@ -244,6 +271,23 @@ static void server_stdin_handler(struct tevent_context *event_ctx,
 /*
  main server helpers.
 */
+
+int die_if_parent_died(void)
+{
+#ifdef HAVE_PRCTL
+    int ret;
+
+    errno = 0;
+    ret = prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
+    if (ret != 0) {
+        ret = errno;
+        DEBUG(2, ("prctl failed [%d]: %s", ret, strerror(ret)));
+        return ret;
+    }
+#endif
+    return EOK;
+}
+
 int server_setup(const char *name, int flags,
                  const char *conf_entry,
                  struct main_context **main_ctx)
diff --git a/server/util/signal.m4 b/server/util/signal.m4
index a778020..747c7db 100644
--- a/server/util/signal.m4
+++ b/server/util/signal.m4
@@ -1 +1 @@
-AC_CHECK_FUNCS(sigprocmask sigblock sigaction getpgrp)
+AC_CHECK_FUNCS(sigprocmask sigblock sigaction getpgrp prctl)
diff --git a/server/util/util.h b/server/util/util.h
index e11bc51..8796529 100644
--- a/server/util/util.h
+++ b/server/util/util.h
@@ -107,6 +107,7 @@ struct main_context {
     struct confdb_ctx *confdb_ctx;
 };
 
+int die_if_parent_died(void);
 int server_setup(const char *name, int flags,
                  const char *conf_entry,
                  struct main_context **main_ctx);
-- 
1.6.2.5

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to