From cfce21281a835dbc7d7bb9560e4339f4c1acf907 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 9 Sep 2016 07:12:11 +0200 Subject: [PATCH] s4/messaging: messaging_dgm_ref talloc hierarchy fix Ensure the messaging dgm context goes away *before* the tevent context. The messaging dgm context will likely have active fd or timer events, their rundown will touch the associated tevent context. Otoh, I deliberately don't free the imessaging context here, that's going to happen as part of freeing the talloc_autofree_context() as before. I think it suffers the same problem, eg imessaging_deregister() works on an imessaging_context that might already be freed. But as it works, don't change it. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source4/lib/messaging/messaging.c | 29 +++++++++++++++++++++++++++++ source4/lib/messaging/messaging.h | 1 + source4/smbd/server.c | 8 ++++++++ 3 files changed, 38 insertions(+) diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 486d602dbb6..0f3891ea2e0 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -293,6 +293,31 @@ static void imessaging_dgm_recv(const uint8_t *buf, size_t buf_len, int *fds, size_t num_fds, void *private_data); +/* Keep a list of imessaging contexts */ +static struct imessaging_context *msg_ctxs; + +static int imessaging_context_destructor(struct imessaging_context *msg) +{ + DLIST_REMOVE(msg_ctxs, msg); + return 0; +} + +/* + * Cleanup messaging dgm contexts + * + * We must make sure to unref all messaging_dgm_ref's *before* the + * tevent context goes away. Only when the last ref is freed, the + * refcounted messaging dgm context will be freed. + */ +void imessaging_dgm_unref_all(void) +{ + struct imessaging_context *msg = NULL; + + for (msg = msg_ctxs; msg != NULL; msg = msg->next) { + TALLOC_FREE(msg->msg_dgm_ref); + } +} + /* create the listening socket and setup the dispatcher */ @@ -316,6 +341,8 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx, return NULL; } + talloc_set_destructor(msg, imessaging_context_destructor); + /* create the messaging directory if needed */ lock_dir = lpcfg_lock_directory(lp_ctx); @@ -374,6 +401,8 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx, imessaging_register(msg, NULL, MSG_IRPC, irpc_handler); IRPC_REGISTER(msg, irpc, IRPC_UPTIME, irpc_uptime, msg); + DLIST_ADD(msg_ctxs, msg); + return msg; fail: talloc_free(msg); diff --git a/source4/lib/messaging/messaging.h b/source4/lib/messaging/messaging.h index 2efab94ae55..3b76b45e5c4 100644 --- a/source4/lib/messaging/messaging.h +++ b/source4/lib/messaging/messaging.h @@ -44,6 +44,7 @@ struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct server_id server_id, struct tevent_context *ev); +void imessaging_dgm_unref_all(void); int imessaging_cleanup(struct imessaging_context *msg); struct imessaging_context *imessaging_client_init(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, diff --git a/source4/smbd/server.c b/source4/smbd/server.c index 2399f4f8454..28ecaca5754 100644 --- a/source4/smbd/server.c +++ b/source4/smbd/server.c @@ -284,6 +284,12 @@ static void show_build(void) exit(0); } +static int event_ctx_destructor(struct tevent_context *event_ctx) +{ + imessaging_dgm_unref_all(); + return 0; +} + /* main server. */ @@ -422,6 +428,8 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ exit_daemon("Initializing event context failed", EACCES); } + talloc_set_destructor(event_ctx, event_ctx_destructor); + if (opt_interactive) { /* terminate when stdin goes away */ stdin_event_flags = TEVENT_FD_READ; -- 2.34.1