diff options
author | Michael Adam <obnox@samba.org> | 2012-03-15 16:29:27 +0100 |
---|---|---|
committer | Michael Adam <obnox@samba.org> | 2012-03-15 18:41:37 +0100 |
commit | c80f70390c3763d5d7248979db9542cd05b7cb44 (patch) | |
tree | a0f96da41205705839cec1dead1fc1762051a2e5 /source3/lib | |
parent | e5ebe67e3837cf4da0ae2c3d00c72a244b8f202f (diff) | |
download | samba-c80f70390c3763d5d7248979db9542cd05b7cb44.tar.gz samba-c80f70390c3763d5d7248979db9542cd05b7cb44.tar.bz2 samba-c80f70390c3763d5d7248979db9542cd05b7cb44.zip |
s3:smbd: let smbd/nmbd/winbindd child processes terminate if the parent process died.
This applies to all child processes making use of reinit_after_fork().
It is implemented by establishing a pipe between parent and child.
The child watches for EOF on the read end of the pipe, indidcating
an exited parent.
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/util.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/source3/lib/util.c b/source3/lib/util.c index 822db43fef..fa2cc9fd83 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -356,6 +356,46 @@ ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos #endif } +static int reinit_after_fork_pipe[2] = { -1, -1 }; + +NTSTATUS init_before_fork(void) +{ + int ret; + + ret = pipe(reinit_after_fork_pipe); + if (ret == -1) { + NTSTATUS status; + + status = map_nt_error_from_unix_common(errno); + + DEBUG(0, ("Error creating child_pipe: %s\n", + nt_errstr(status))); + + return status; + } + + return NT_STATUS_OK; +} + +/** + * Detect died parent by detecting EOF on the pipe + */ +static void reinit_after_fork_pipe_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + char c; + + if (read(reinit_after_fork_pipe[0], &c, 1) != 1) { + /* + * we have reached EOF on stdin, which means the + * parent has exited. Shutdown the server + */ + (void)kill(getpid(), SIGTERM); + } +} + NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, struct event_context *ev_ctx, @@ -363,6 +403,11 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, { NTSTATUS status = NT_STATUS_OK; + if (reinit_after_fork_pipe[1] != -1) { + close(reinit_after_fork_pipe[1]); + reinit_after_fork_pipe[1] = -1; + } + /* Reset the state of the random * number generation system, so * children do not get the same random @@ -380,6 +425,17 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, smb_panic(__location__ ": Failed to re-initialise event context"); } + if (reinit_after_fork_pipe[0] != -1) { + struct tevent_fd *fde; + + fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */, + reinit_after_fork_pipe[0], TEVENT_FD_READ, + reinit_after_fork_pipe_handler, NULL); + if (fde == NULL) { + smb_panic(__location__ ": Failed to add reinit_after_fork pipe event"); + } + } + if (msg_ctx) { /* * For clustering, we need to re-init our ctdbd connection after the |