s4:messaging: allow imessaging_post_handler() to free the messaging context from...
authorStefan Metzmacher <metze@samba.org>
Sat, 19 May 2018 08:14:25 +0000 (10:14 +0200)
committerRalph Boehme <slow@samba.org>
Wed, 11 Jul 2018 21:04:24 +0000 (23:04 +0200)
In usecases like using messaging_client_init() with irpc processing we may
free the imessaging_context during the messaging handler.
imessaging_post_handler() is not yet really used, but it will change in
the next commits. imessaging_post_state is a child of imessaging_context
and might be implicitly free'ed before the explicit TALLOC_FREE(state).

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source4/lib/messaging/messaging.c

index b8d4e50f12c758dd6945dd8b7c78331fc14c8dd8..8903322bdc7f47957531ea1e710310ca88f620df 100644 (file)
@@ -433,18 +433,48 @@ fail:
 
 struct imessaging_post_state {
        struct imessaging_context *msg_ctx;
+       struct imessaging_post_state **busy_ref;
        size_t buf_len;
        uint8_t buf[];
 };
 
+static int imessaging_post_state_destructor(struct imessaging_post_state *state)
+{
+       if (state->busy_ref != NULL) {
+               *state->busy_ref = NULL;
+               state->busy_ref = NULL;
+       }
+       return 0;
+}
+
 static void imessaging_post_handler(struct tevent_context *ev,
                                    struct tevent_immediate *ti,
                                    void *private_data)
 {
        struct imessaging_post_state *state = talloc_get_type_abort(
                private_data, struct imessaging_post_state);
+
+       /*
+        * In usecases like using messaging_client_init() with irpc processing
+        * we may free the imessaging_context during the messaging handler.
+        * imessaging_post_state is a child of imessaging_context and
+        * might be implicitly free'ed before the explicit TALLOC_FREE(state).
+        *
+        * The busy_ref pointer makes sure the destructor clears
+        * the local 'state' variable.
+        */
+
+       SMB_ASSERT(state->busy_ref == NULL);
+       state->busy_ref = &state;
+
        imessaging_dgm_recv(ev, state->buf, state->buf_len, NULL, 0,
                            state->msg_ctx);
+
+       if (state == NULL) {
+               return;
+       }
+
+       state->busy_ref = NULL;
        TALLOC_FREE(state);
 }
 
@@ -461,6 +491,8 @@ static int imessaging_post_self(struct imessaging_context *msg,
        }
        talloc_set_name_const(state, "struct imessaging_post_state");
 
+       talloc_set_destructor(state, imessaging_post_state_destructor);
+
        ti = tevent_create_immediate(state);
        if (ti == NULL) {
                TALLOC_FREE(state);
@@ -468,6 +500,7 @@ static int imessaging_post_self(struct imessaging_context *msg,
        }
 
        state->msg_ctx = msg;
+       state->busy_ref = NULL;
        state->buf_len = buf_len;
        memcpy(state->buf, buf, buf_len);