From: Gary Lockyer Date: Thu, 13 Sep 2018 21:45:38 +0000 (+1200) Subject: source4 smbd prefork: Cleanup messaging on restart X-Git-Tag: tdb-1.3.17~650 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46b164de67689c57d316701557b9847a0b9e45c1;p=thirdparty%2Fsamba.git source4 smbd prefork: Cleanup messaging on restart Clean up names registered in messaging for a terminated process. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett --- diff --git a/selftest/knownfail.d/prefork_restart b/selftest/knownfail.d/prefork_restart deleted file mode 100644 index 020199cd9b4..00000000000 --- a/selftest/knownfail.d/prefork_restart +++ /dev/null @@ -1,8 +0,0 @@ -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_ldap_all_workers_restart -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_ldap_master_restart -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_ldap_worker_restart -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_master_restart_backoff -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_rpc_all_workers_restart -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_rpc_master_restart -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_rpc_worker_zero_restart -^samba.tests.prefork_restart.samba.tests.prefork_restart.PreforkProcessRestartTests.test_worker_restart_backoff diff --git a/source4/smbd/process_prefork.c b/source4/smbd/process_prefork.c index a0232906777..c62f08fbbfe 100644 --- a/source4/smbd/process_prefork.c +++ b/source4/smbd/process_prefork.c @@ -34,6 +34,7 @@ #include "param/param.h" #include "ldb_wrap.h" #include "lib/util/tfork.h" +#include "lib/messaging/irpc.h" #define min(a, b) (((a) < (b)) ? (a) : (b)) @@ -63,7 +64,9 @@ static void prefork_child_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data); -static void setup_handlers(struct tevent_context *ev, int from_parent_fd); +static void setup_handlers(struct tevent_context *ev, + struct loadparm_context *lp_ctx, + int from_parent_fd); /* * State needed to restart the master process or a worker process if they @@ -120,7 +123,7 @@ static void sigterm_signal_handler(struct tevent_context *ev, } #endif DBG_NOTICE("Exiting pid %d on SIGTERM\n", getpid()); - talloc_free(ev); + TALLOC_FREE(ev); exit(127); } @@ -143,6 +146,40 @@ static void prefork_reload_after_fork(void) } } +/* + * clean up any messaging associated with the old process. + * + */ +static void irpc_cleanup( + struct loadparm_context *lp_ctx, + struct tevent_context *ev, + pid_t pid) +{ + TALLOC_CTX *mem_ctx = talloc_new(NULL); + struct imessaging_context *msg_ctx = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (mem_ctx == NULL) { + DBG_ERR("OOM cleaning up irpc\n"); + return; + } + msg_ctx = imessaging_client_init(mem_ctx, lp_ctx, ev); + if (msg_ctx == NULL) { + DBG_ERR("Unable to create imessaging_context\n"); + TALLOC_FREE(mem_ctx); + return; + } + status = imessaging_process_cleanup(msg_ctx, pid); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("imessaging_process_cleanup returned (%s)\n", + nt_errstr(status)); + TALLOC_FREE(mem_ctx); + return; + } + + TALLOC_FREE(mem_ctx); +} + /* handle EOF on the parent-to-all-children pipe in the child */ @@ -150,10 +187,23 @@ static void prefork_pipe_handler(struct tevent_context *event_ctx, struct tevent_fd *fde, uint16_t flags, void *private_data) { - /* free the fde which removes the event and stops it firing again */ + struct loadparm_context *lp_ctx = NULL; + pid_t pid; + + /* + * free the fde which removes the event and stops it firing again + */ TALLOC_FREE(fde); + + /* + * Clean up any irpc end points this process had. + */ + pid = getpid(); + lp_ctx = talloc_get_type_abort(private_data, struct loadparm_context); + irpc_cleanup(lp_ctx, event_ctx, pid); + DBG_NOTICE("Child %d exiting\n", getpid()); - talloc_free(event_ctx); + TALLOC_FREE(event_ctx); exit(0); } @@ -238,7 +288,7 @@ static void prefork_fork_master( smb_panic("Failed to re-initialise tevent after fork"); } prefork_reload_after_fork(); - setup_handlers(ev, from_parent_fd); + setup_handlers(ev, lp_ctx, from_parent_fd); if (service_details->inhibit_pre_fork) { task = new_task_fn( @@ -272,7 +322,23 @@ static void prefork_fork_master( if (task == NULL) { TALLOC_FREE(ev); TALLOC_FREE(ev2); - exit(0); + exit(127); + } + + /* + * Register an irpc name that can be used by the samba-tool processes + * command + */ + { + struct talloc_ctx *ctx = talloc_new(NULL); + char *name = NULL; + if (ctx == NULL) { + DBG_ERR("Out of memory"); + exit(127); + } + name = talloc_asprintf(ctx, "prefork-master-%s", service_name); + irpc_add_name(task->msg_ctx, name); + TALLOC_FREE(ctx); } { @@ -405,6 +471,8 @@ static void prefork_child_pipe_handler(struct tevent_context *ev, rc = talloc_get_type_abort(private_data, struct restart_context); pid = tfork_child_pid(rc->t); errno = 0; + + irpc_cleanup(rc->lp_ctx, ev, pid); status = tfork_status(&rc->t, false); if (status == -1) { DBG_ERR("Parent %d, Child %d terminated, " @@ -482,12 +550,16 @@ static void prefork_accept_connection( private_data, process_context); } -static void setup_handlers(struct tevent_context *ev, int from_parent_fd) { +static void setup_handlers( + struct tevent_context *ev, + struct loadparm_context *lp_ctx, + int from_parent_fd) +{ struct tevent_fd *fde = NULL; struct tevent_signal *se = NULL; fde = tevent_add_fd(ev, ev, from_parent_fd, TEVENT_FD_READ, - prefork_pipe_handler, NULL); + prefork_pipe_handler, lp_ctx); if (fde == NULL) { smb_panic("Failed to add fd handler after fork"); } @@ -566,7 +638,7 @@ static void prefork_fork_worker(struct task_server *task, tevent_fd_set_auto_close(fde); } else { close(control_pipe[1]); - setup_handlers(ev2, control_pipe[0]); + setup_handlers(ev2, lp_ctx, control_pipe[0]); /* * tfork uses malloc */ @@ -580,6 +652,19 @@ static void prefork_fork_worker(struct task_server *task, if (service_details->post_fork != NULL) { service_details->post_fork(task, pd); } + { + struct talloc_ctx *ctx = talloc_new(NULL); + char *name = NULL; + if (ctx == NULL) { + smb_panic("OOM allocating talloc context\n"); + } + name = talloc_asprintf(ctx, + "prefork-worker-%s-%d", + service_name, + pd->instances); + irpc_add_name(task->msg_ctx, name); + TALLOC_FREE(ctx); + } tevent_loop_wait(ev2); talloc_free(ev2); exit(0); @@ -620,6 +705,7 @@ static void prefork_terminate_task(struct tevent_context *ev, void *process_context) { DBG_DEBUG("called with reason[%s]\n", reason); + TALLOC_FREE(ev); if (fatal == true) { exit(127); } else {