From dd8aaf74198c084fd0aa712d56c4511978f04ebe Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 3 Aug 2009 11:55:36 +0200 Subject: 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 deletion(-) diff --git a/server/providers/data_provider.c b/server/providers/data_provider.c index b95292546..f0ecd30bb 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 c93c4531e..49885edc6 100644 --- a/server/providers/data_provider_be.c +++ b/server/providers/data_provider_be.c @@ -1109,6 +1109,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 248d53843..418e2f9f6 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 92fa4aecb..bff2f7cc9 100644 --- a/server/responder/pam/pamsrv.c +++ b/server/responder/pam/pamsrv.c @@ -227,6 +227,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 fd6e4cdc4..d20a823c7 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 +#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 a778020e7..747c7dbf3 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 e11bc51cf..879652924 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); -- cgit