tevent: split out tevent_common_invoke_immediate_handler()
authorStefan Metzmacher <metze@samba.org>
Tue, 22 Jul 2014 11:08:42 +0000 (13:08 +0200)
committerRalph Boehme <slow@samba.org>
Wed, 11 Jul 2018 21:04:20 +0000 (23:04 +0200)
We'll undo the 0.9.36 ABI change on the 0.9.37 release
at the end of this patchset.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
lib/tevent/ABI/tevent-0.9.36.sigs
lib/tevent/tevent_immediate.c
lib/tevent/tevent_internal.h
lib/tevent/tevent_threads.c

index bb89cc72d1e10908ea69b54e7ff5e4bf572eab39..451e380688c862d6ba83a15bc7e9f9793ff07434 100644 (file)
@@ -32,6 +32,7 @@ tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
 tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
 tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
 tevent_common_have_events: bool (struct tevent_context *)
+tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *)
 tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *)
 tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *)
 tevent_common_loop_immediate: bool (struct tevent_context *)
index c640a565b08250b0269dddfb9c19a7e136c500ea..0649d1eacf2746a361c8e16ba2c5496f6a3c53d2 100644 (file)
 static void tevent_common_immediate_cancel(struct tevent_immediate *im)
 {
        const char *create_location = im->create_location;
+       bool busy = im->busy;
+
+       if (im->destroyed) {
+               tevent_abort(im->event_ctx, "tevent_immediate use after free");
+               return;
+       }
 
        if (!im->event_ctx) {
                return;
@@ -51,9 +57,12 @@ static void tevent_common_immediate_cancel(struct tevent_immediate *im)
 
        *im = (struct tevent_immediate) {
                .create_location        = create_location,
+               .busy                   = busy,
        };
 
-       talloc_set_destructor(im, NULL);
+       if (!busy) {
+               talloc_set_destructor(im, NULL);
+       }
 }
 
 /*
@@ -61,7 +70,21 @@ static void tevent_common_immediate_cancel(struct tevent_immediate *im)
 */
 static int tevent_common_immediate_destructor(struct tevent_immediate *im)
 {
+       if (im->destroyed) {
+               tevent_common_check_double_free(im,
+                                               "tevent_immediate double free");
+               goto done;
+       }
+
        tevent_common_immediate_cancel(im);
+
+       im->destroyed = true;
+
+done:
+       if (im->busy) {
+               return -1;
+       }
+
        return 0;
 }
 
@@ -76,6 +99,7 @@ void tevent_common_schedule_immediate(struct tevent_immediate *im,
                                      const char *location)
 {
        const char *create_location = im->create_location;
+       bool busy = im->busy;
 
        tevent_common_immediate_cancel(im);
 
@@ -90,6 +114,7 @@ void tevent_common_schedule_immediate(struct tevent_immediate *im,
                .handler_name           = handler_name,
                .create_location        = create_location,
                .schedule_location      = location,
+               .busy                   = busy,
        };
 
        DLIST_ADD_END(ev->immediate_events, im);
@@ -100,18 +125,14 @@ void tevent_common_schedule_immediate(struct tevent_immediate *im,
                     handler_name, im);
 }
 
-/*
-  trigger the first immediate event and return true
-  if no event was triggered return false
-*/
-bool tevent_common_loop_immediate(struct tevent_context *ev)
+int tevent_common_invoke_immediate_handler(struct tevent_immediate *im,
+                                          bool *removed)
 {
-       struct tevent_immediate *im = ev->immediate_events;
-       tevent_immediate_handler_t handler;
-       void *private_data;
+       struct tevent_context *ev = im->event_ctx;
+       struct tevent_immediate cur = *im;
 
-       if (!im) {
-               return false;
+       if (removed != NULL) {
+               *removed = false;
        }
 
        tevent_debug(ev, TEVENT_DEBUG_TRACE,
@@ -122,21 +143,41 @@ bool tevent_common_loop_immediate(struct tevent_context *ev)
         * remember the handler and then clear the event
         * the handler might reschedule the event
         */
-       handler = im->handler;
-       private_data = im->private_data;
 
-       DLIST_REMOVE(im->event_ctx->immediate_events, im);
-       im->event_ctx           = NULL;
-       im->handler             = NULL;
-       im->private_data        = NULL;
-       im->handler_name        = NULL;
-       im->schedule_location   = NULL;
-       im->cancel_fn           = NULL;
-       im->additional_data     = NULL;
+       im->busy = true;
+       im->handler_name = NULL;
+       tevent_common_immediate_cancel(im);
+       cur.handler(ev, im, cur.private_data);
+       im->busy = false;
+
+       if (im->destroyed) {
+               talloc_set_destructor(im, NULL);
+               TALLOC_FREE(im);
+               if (removed != NULL) {
+                       *removed = true;
+               }
+       }
+
+       return 0;
+}
+
+/*
+  trigger the first immediate event and return true
+  if no event was triggered return false
+*/
+bool tevent_common_loop_immediate(struct tevent_context *ev)
+{
+       struct tevent_immediate *im = ev->immediate_events;
+       int ret;
 
-       talloc_set_destructor(im, NULL);
+       if (!im) {
+               return false;
+       }
 
-       handler(ev, im, private_data);
+       ret = tevent_common_invoke_immediate_handler(im, NULL);
+       if (ret != 0) {
+               tevent_abort(ev, "tevent_common_invoke_immediate_handler() failed");
+       }
 
        return true;
 }
index 8126414d6836cec54a4b67c46bfcb9183f0b79fc..d74684c72c2cf610f48f7c34659db9aa1379a90b 100644 (file)
@@ -203,6 +203,8 @@ struct tevent_timer {
 struct tevent_immediate {
        struct tevent_immediate *prev, *next;
        struct tevent_context *event_ctx;
+       bool busy;
+       bool destroyed;
        tevent_immediate_handler_t handler;
        /* this is private for the specific handler */
        void *private_data;
@@ -367,6 +369,8 @@ void tevent_common_schedule_immediate(struct tevent_immediate *im,
                                      void *private_data,
                                      const char *handler_name,
                                      const char *location);
+int tevent_common_invoke_immediate_handler(struct tevent_immediate *im,
+                                          bool *removed);
 bool tevent_common_loop_immediate(struct tevent_context *ev);
 void tevent_common_threaded_activate_immediate(struct tevent_context *ev);
 
index efdac9856dd16016e129bab7a3d988d6cf579f24..9410765266e4801e76d1de456213c38f17877928 100644 (file)
@@ -482,6 +482,12 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx,
        if ((im->event_ctx != NULL) || (handler == NULL)) {
                abort();
        }
+       if (im->destroyed) {
+               abort();
+       }
+       if (im->busy) {
+               abort();
+       }
 
        *im = (struct tevent_immediate) {
                .event_ctx              = ev,