s4/messaging: messaging_dgm_ref talloc hierarchy fix
authorRalph Boehme <slow@samba.org>
Fri, 9 Sep 2016 05:12:11 +0000 (07:12 +0200)
committerJeremy Allison <jra@samba.org>
Mon, 12 Sep 2016 22:19:26 +0000 (00:19 +0200)
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 <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source4/lib/messaging/messaging.c
source4/lib/messaging/messaging.h
source4/smbd/server.c

index 486d602dbb62245015cbe3e273e67ae8a70a8a54..0f3891ea2e0773ea3f3d7d3c251092e1c287d195 100644 (file)
@@ -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);
index 2efab94ae5547974c56ea8fd3acbc819591c9fe9..3b76b45e5c466d205593e595c21f671b957fecac 100644 (file)
@@ -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,
index 2399f4f84544ed921a5ff638bd158d560f455c52..28ecaca575449239099e7ea29e7e31b0e681cc7e 100644 (file)
@@ -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;