summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorGary Lockyer <gary@catalyst.net.nz>2018-09-14 09:45:38 +1200
committerAndrew Bartlett <abartlet@samba.org>2018-11-23 08:25:20 +0100
commit46b164de67689c57d316701557b9847a0b9e45c1 (patch)
tree6b8cee115ee591b1e98f1e734acc648feafdd799 /source4
parent11d424e1999e50f036ce2b33411f6f607c60a487 (diff)
downloadsamba-46b164de67689c57d316701557b9847a0b9e45c1.tar.gz
source4 smbd prefork: Cleanup messaging on restart
Clean up names registered in messaging for a terminated process. Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4')
-rw-r--r--source4/smbd/process_prefork.c104
1 files changed, 95 insertions, 9 deletions
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);
}
@@ -144,16 +147,63 @@ 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
*/
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 {