summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-08-07 17:21:54 +1000
committerAndrew Tridgell <tridge@samba.org>2009-08-07 17:24:48 +1000
commitc271dc998ba25101a46e7d4b2187567a07588ca2 (patch)
tree20270a68759dc336855a60ff704d201f91acc936
parentcfc0cabb27c7323930b96dd93befa955bacd6cde (diff)
downloadsamba-c271dc998ba25101a46e7d4b2187567a07588ca2.tar.gz
samba-c271dc998ba25101a46e7d4b2187567a07588ca2.tar.bz2
samba-c271dc998ba25101a46e7d4b2187567a07588ca2.zip
ensure that child tasks die when the parent dies
Previously we relied on process groups and SIGTERM to ensure that child tasks died in the standard process model when the parent task died. This doesn't work when the server is run in interactive mode, as in that case we don't call become_daemon() and don't get a separate process group. The fix is to have a pipe held open by the parent server process, and inherited by child tasks. If the parent exits then the write side of the pipe is implicitly closed, which causes an event in the child tasks that causes them to exit
-rw-r--r--source4/smbd/process_standard.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c
index 137e0a7ce0..730e185e5a 100644
--- a/source4/smbd/process_standard.c
+++ b/source4/smbd/process_standard.c
@@ -44,15 +44,31 @@ static int none_setproctitle(const char *fmt, ...)
}
#endif
+/* we hold a pipe open in the parent, and the any child
+ processes wait for EOF on that pipe. This ensures that
+ children die when the parent dies */
+static int child_pipe[2];
+
/*
called when the process model is selected
*/
static void standard_model_init(struct tevent_context *ev)
{
+ pipe(child_pipe);
signal(SIGCHLD, SIG_IGN);
}
/*
+ handle EOF on the child pipe
+*/
+static void standard_pipe_handler(struct tevent_context *event_ctx, struct tevent_fd *fde,
+ uint16_t flags, void *private_data)
+{
+ DEBUG(10,("Child %d exiting\n", (int)getpid()));
+ exit(0);
+}
+
+/*
called when a listening socket becomes readable.
*/
static void standard_accept_connection(struct tevent_context *ev,
@@ -114,6 +130,10 @@ static void standard_accept_connection(struct tevent_context *ev,
DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n"));
}
+ tevent_add_fd(ev2, ev2, child_pipe[0], TEVENT_FD_READ,
+ standard_pipe_handler, NULL);
+ close(child_pipe[1]);
+
/* Ensure that the forked children do not expose identical random streams */
set_need_random_reseed();
@@ -177,6 +197,10 @@ static void standard_new_task(struct tevent_context *ev,
DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n"));
}
+ tevent_add_fd(ev2, ev2, child_pipe[0], TEVENT_FD_READ,
+ standard_pipe_handler, NULL);
+ close(child_pipe[1]);
+
/* Ensure that the forked children do not expose identical random streams */
set_need_random_reseed();