mirror of
https://github.com/samba-team/samba.git
synced 2025-08-03 04:22:09 +03:00
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>
This commit is contained in:
@ -484,6 +484,7 @@ char *unix_clean_name(TALLOC_CTX *ctx, const char *s);
|
|||||||
char *clean_name(TALLOC_CTX *ctx, const char *s);
|
char *clean_name(TALLOC_CTX *ctx, const char *s);
|
||||||
ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos);
|
ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos);
|
||||||
int set_blocking(int fd, bool set);
|
int set_blocking(int fd, bool set);
|
||||||
|
NTSTATUS init_before_fork(void);
|
||||||
NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
|
NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
|
||||||
struct event_context *ev_ctx,
|
struct event_context *ev_ctx,
|
||||||
bool parent_longlived);
|
bool parent_longlived);
|
||||||
|
@ -356,6 +356,46 @@ ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos
|
|||||||
#endif
|
#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,
|
NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
|
||||||
struct event_context *ev_ctx,
|
struct event_context *ev_ctx,
|
||||||
@ -363,6 +403,11 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
|
|||||||
{
|
{
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
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
|
/* Reset the state of the random
|
||||||
* number generation system, so
|
* number generation system, so
|
||||||
* children do not get the same random
|
* 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");
|
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) {
|
if (msg_ctx) {
|
||||||
/*
|
/*
|
||||||
* For clustering, we need to re-init our ctdbd connection after the
|
* For clustering, we need to re-init our ctdbd connection after the
|
||||||
|
@ -951,6 +951,17 @@ static bool open_sockets(bool isdaemon, int port)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not initialize the parent-child-pipe before becoming
|
||||||
|
* a daemon: this is used to detect a died parent in the child
|
||||||
|
* process.
|
||||||
|
*/
|
||||||
|
status = init_before_fork();
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!nmbd_setup_sig_term_handler(msg))
|
if (!nmbd_setup_sig_term_handler(msg))
|
||||||
exit(1);
|
exit(1);
|
||||||
if (!nmbd_setup_stdin_handler(msg, !Fork))
|
if (!nmbd_setup_stdin_handler(msg, !Fork))
|
||||||
|
@ -57,6 +57,8 @@ struct smbd_parent_context {
|
|||||||
/* the list of current child processes */
|
/* the list of current child processes */
|
||||||
struct smbd_child_pid *children;
|
struct smbd_child_pid *children;
|
||||||
size_t num_children;
|
size_t num_children;
|
||||||
|
/* pipe for detecting death of parent process in child: */
|
||||||
|
int child_pipe[2];
|
||||||
|
|
||||||
struct timed_event *cleanup_te;
|
struct timed_event *cleanup_te;
|
||||||
};
|
};
|
||||||
@ -1231,6 +1233,17 @@ extern void build_options(bool screen);
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not initialize the parent-child-pipe before becoming
|
||||||
|
* a daemon: this is used to detect a died parent in the child
|
||||||
|
* process.
|
||||||
|
*/
|
||||||
|
status = init_before_fork();
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
smbd_server_conn->msg_ctx = msg_ctx;
|
smbd_server_conn->msg_ctx = msg_ctx;
|
||||||
|
|
||||||
parent = talloc_zero(ev_ctx, struct smbd_parent_context);
|
parent = talloc_zero(ev_ctx, struct smbd_parent_context);
|
||||||
|
@ -1461,6 +1461,17 @@ int main(int argc, char **argv, char **envp)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not initialize the parent-child-pipe before becoming
|
||||||
|
* a daemon: this is used to detect a died parent in the child
|
||||||
|
* process.
|
||||||
|
*/
|
||||||
|
status = init_before_fork();
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
winbindd_register_handlers(!Fork);
|
winbindd_register_handlers(!Fork);
|
||||||
|
|
||||||
status = init_system_info();
|
status = init_system_info();
|
||||||
|
Reference in New Issue
Block a user