diff options
author | Stefan Metzmacher <metze@samba.org> | 2014-07-22 13:08:42 +0200 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2018-07-11 23:04:20 +0200 |
commit | 6740718e0e7db82563870ff398de90dac8f09228 (patch) | |
tree | 976117d616951499186241af7056be1d82487045 /lib/tevent | |
parent | a85ee852accd9137dbffa1e41df8618123b00450 (diff) | |
download | samba-6740718e0e7db82563870ff398de90dac8f09228.tar.gz |
tevent: split out tevent_common_invoke_immediate_handler()
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>
Diffstat (limited to 'lib/tevent')
-rw-r--r-- | lib/tevent/ABI/tevent-0.9.36.sigs | 1 | ||||
-rw-r--r-- | lib/tevent/tevent_immediate.c | 87 | ||||
-rw-r--r-- | lib/tevent/tevent_internal.h | 4 | ||||
-rw-r--r-- | lib/tevent/tevent_threads.c | 6 |
4 files changed, 75 insertions, 23 deletions
diff --git a/lib/tevent/ABI/tevent-0.9.36.sigs b/lib/tevent/ABI/tevent-0.9.36.sigs index bb89cc72d1e..451e380688c 100644 --- a/lib/tevent/ABI/tevent-0.9.36.sigs +++ b/lib/tevent/ABI/tevent-0.9.36.sigs @@ -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 *) diff --git a/lib/tevent/tevent_immediate.c b/lib/tevent/tevent_immediate.c index c640a565b08..0649d1eacf2 100644 --- a/lib/tevent/tevent_immediate.c +++ b/lib/tevent/tevent_immediate.c @@ -31,6 +31,12 @@ 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; } diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index 8126414d683..d74684c72c2 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -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); diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c index efdac9856dd..9410765266e 100644 --- a/lib/tevent/tevent_threads.c +++ b/lib/tevent/tevent_threads.c @@ -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, |