From a7155733a91e8c87c059b221a68bbc48d6a20be6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Nov 2017 23:29:42 +0100 Subject: [PATCH 01/17] Revert "tevent: Fix a race condition" This reverts commit 6a43b1b17902c8fbc319e13f31f6c9177f38371c. This will reapplied shortly in the correct order relative to other backports. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_threads.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c index 197ad1d..8197323 100644 --- a/lib/tevent/tevent_threads.c +++ b/lib/tevent/tevent_threads.c @@ -434,7 +434,7 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, { #ifdef HAVE_PTHREAD struct tevent_context *ev; - int ret, wakeup_fd; + int ret; ret = pthread_mutex_lock(&tctx->event_ctx_mutex); if (ret != 0) { @@ -442,7 +442,6 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, } ev = tctx->event_ctx; - wakeup_fd = tctx->wakeup_fd; ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); if (ret != 0) { @@ -490,7 +489,7 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, * than a noncontended one. So I'd opt for the lower footprint * initially. Maybe we have to change that later. */ - tevent_common_wakeup_fd(wakeup_fd); + tevent_common_wakeup_fd(tctx->wakeup_fd); #else /* * tevent_threaded_context_create() returned NULL with ENOSYS... -- 1.9.1 From 5dddf32ab79151c26a9e95aff13b1cae8f482815 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 Jun 2017 07:23:27 +0200 Subject: [PATCH 02/17] tevent: Fix a typo Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit b03475048a49db78422d1bfc11f2c69d56fbf87f) --- lib/tevent/tevent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index ba4bb4d..728cf62 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -1777,7 +1777,7 @@ void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, * * It is the duty of the caller of tevent_threaded_context_create() to * keep the event context around longer than any - * tevent_threaded_context. tevent will abort if ev is talllc_free'ed + * tevent_threaded_context. tevent will abort if ev is talloc_free'ed * with an active tevent_threaded_context. * * If tevent is build without pthread support, this always returns -- 1.9.1 From c7199c771bcd17cafc2f28fd728c3ba9bb5e4a9f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 Jun 2017 06:58:37 +0200 Subject: [PATCH 03/17] tevent: Factor out context initialization Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 97d912d99afb115e17f683a55aef447dc92ced49) --- lib/tevent/tevent.c | 59 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 65b101f..68b9db6 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -392,46 +392,26 @@ int tevent_common_context_destructor(struct tevent_context *ev) return 0; } -/* - create a event_context structure for a specific implemementation. - This must be the first events call, and all subsequent calls pass - this event_context as the first element. Event handlers also - receive this as their first argument. - - This function is for allowing third-party-applications to hook in gluecode - to their own event loop code, so that they can make async usage of our client libs - - NOTE: use tevent_context_init() inside of samba! -*/ -struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, - const struct tevent_ops *ops, - void *additional_data) +static int tevent_common_context_constructor(struct tevent_context *ev) { - struct tevent_context *ev; int ret; - ev = talloc_zero(mem_ctx, struct tevent_context); - if (!ev) return NULL; - #ifdef HAVE_PTHREAD ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork); if (ret != 0) { - talloc_free(ev); - return NULL; + return ret; } ret = pthread_mutex_init(&ev->scheduled_mutex, NULL); if (ret != 0) { - talloc_free(ev); - return NULL; + return ret; } ret = pthread_mutex_lock(&tevent_contexts_mutex); if (ret != 0) { pthread_mutex_destroy(&ev->scheduled_mutex); - talloc_free(ev); - return NULL; + return ret; } DLIST_ADD(tevent_contexts, ev); @@ -440,11 +420,40 @@ struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, if (ret != 0) { abort(); } - #endif talloc_set_destructor(ev, tevent_common_context_destructor); + return 0; +} + +/* + create a event_context structure for a specific implemementation. + This must be the first events call, and all subsequent calls pass + this event_context as the first element. Event handlers also + receive this as their first argument. + + This function is for allowing third-party-applications to hook in gluecode + to their own event loop code, so that they can make async usage of our client libs + + NOTE: use tevent_context_init() inside of samba! +*/ +struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, + const struct tevent_ops *ops, + void *additional_data) +{ + struct tevent_context *ev; + int ret; + + ev = talloc_zero(mem_ctx, struct tevent_context); + if (!ev) return NULL; + + ret = tevent_common_context_constructor(ev); + if (ret != 0) { + talloc_free(ev); + return NULL; + } + ev->ops = ops; ev->additional_data = additional_data; -- 1.9.1 From 9d20d1bdfb7bd1fead310176147056a2b57b5734 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 Jun 2017 07:16:17 +0200 Subject: [PATCH 04/17] tevent: Re-init threading in tevent_re_initialise Without this threading is not usable after that call Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit afe026d3030c0c05a31de872dd0d120511ba6652) --- lib/tevent/tevent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 68b9db6..7d59c8b 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -884,6 +884,8 @@ int tevent_re_initialise(struct tevent_context *ev) { tevent_common_context_destructor(ev); + tevent_common_context_constructor(ev); + return ev->ops->context_init(ev); } -- 1.9.1 From 5115e8e1166c79c822cb49a8fdf456c7a8f4c285 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 Jun 2017 07:29:11 +0200 Subject: [PATCH 05/17] tevent: Add tevent_re_initialise to threaded test Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit ca715762418284a1a2acc81d40e9e429e407ce14) --- lib/tevent/testsuite.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index 4783ab4..ee29e5b 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -1207,6 +1207,14 @@ static bool test_multi_tevent_threaded_2(struct torture_context *test, ev = tevent_context_init(test); torture_assert(test, ev != NULL, "tevent_context_init failed"); + /* + * tevent_re_initialise used to have a bug where it did not + * re-initialise the thread support after taking it + * down. Excercise that code path. + */ + ret = tevent_re_initialise(ev); + torture_assert(test, ret == 0, "tevent_re_initialise failed"); + tctx = tevent_threaded_context_create(ev, ev); torture_assert(test, tctx != NULL, "tevent_threaded_context_create failed"); -- 1.9.1 From 2f514e47b2faa8f1c985bf7d68509cd790b1b2b7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 24 May 2017 16:21:40 +0200 Subject: [PATCH 06/17] tevent: Fix a memleak on FreeBSD FreeBSD has malloc'ed memory attached to mutexes. We need to clean this up. valgrind really helped here Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 00390ae27b6bd207add571d7975c37951e15a3e5) --- lib/tevent/tevent.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 7d59c8b..f3b18a1 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -341,6 +341,11 @@ int tevent_common_context_destructor(struct tevent_context *ev) DLIST_REMOVE(ev->threaded_contexts, tctx); } + + ret = pthread_mutex_destroy(&ev->scheduled_mutex); + if (ret != 0) { + abort(); + } #endif tevent_common_wakeup_fini(ev); -- 1.9.1 From 9413f1c266b3b2286f25419bc799a6fd45822740 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 24 May 2017 16:22:34 +0200 Subject: [PATCH 07/17] tevent: Fix a race condition in tevent context rundown We protect setting tctx->event_ctx=NULL with tctx->event_ctx_mutex. But in _tevent_threaded_schedule_immediate we have the classic TOCTOU race: After we checked "ev==NULL", looking at tevent_common_context_destructor the event context can go after _tevent_threaded_schedule_immediate checked. We need to serialize things a bit by keeping tctx->event_ctx_mutex locked while we reference "ev", in particular in the DLIST_ADD_END(ev->scheduled_immediates,im); I think the locking hierarchy is still maintained, tevent_atfork_prepare() first locks all the tctx locks, and then the scheduled_mutex. Also, I don't think this will impact parallelism too badly: event_ctx_mutex is only used to protect setting tctx->ev. Found by staring at code while fixing the FreeBSD memleak due to not destroying scheduled_mutex. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Jun 9 00:45:26 CEST 2017 on sn-devel-144 (cherry picked from commit 1828011317b0a8142c3b66fff22661a962760574) --- lib/tevent/tevent_threads.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c index 8197323..8ecda02 100644 --- a/lib/tevent/tevent_threads.c +++ b/lib/tevent/tevent_threads.c @@ -443,15 +443,14 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, ev = tctx->event_ctx; - ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); - if (ret != 0) { - abort(); - } - if (ev == NULL) { /* * Our event context is already gone. */ + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } return; } @@ -479,6 +478,11 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, abort(); } + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + /* * We might want to wake up the main thread under the lock. We * had a slightly similar situation in pthreadpool, changed -- 1.9.1 From 07c3cb6ffde658f0c2b3cca891b7bd06e35b88e3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 15 Jun 2017 11:48:24 +0200 Subject: [PATCH 08/17] tevent_threads: Fix a rundown race introduced with 1828011317b The race is easily reproduced by adding a poll(NULL,0,10) in between the two pthread_mutex_unlock calls in _tevent_threaded_schedule_immediate. Before 1828011317b, the main thread was signalled only after the helper had already unlocked event_ctx_mutex. Full explaination follows: ----------------------------------------------------------------- Inside _tevent_threaded_schedule_immediate() we have: 476 ret = pthread_mutex_unlock(&ev->scheduled_mutex); 477 if (ret != 0) { 478 abort(); 479 } HERE!!!! 481 ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); 482 if (ret != 0) { 483 abort(); 484 } At the HERE!!! point, what happens is tevent_common_threaded_activate_immediate(), which is blocked on ev->scheduled_mutex, get released and does: 514 while (ev->scheduled_immediates != NULL) { 515 struct tevent_immediate *im = ev->scheduled_immediates; 516 DLIST_REMOVE(ev->scheduled_immediates, im); 517 DLIST_ADD_END(ev->immediate_events, im); 518 } - making an immediate event ready to be scheduled. This then returns into epoll_event_loop_once(), which then calls: 910 if (ev->immediate_events && 911 tevent_common_loop_immediate(ev)) { 912 return 0; 913 } which causes the immediate event to fire. This immediate event is the pthread job terminate event, which was previously set up in pthreadpool_tevent_job_signal() by: 198 if (state->tctx != NULL) { 199 /* with HAVE_PTHREAD */ 200 tevent_threaded_schedule_immediate(state->tctx, state->im, 201 pthreadpool_tevent_job_done, 202 state); So we now call pthreadpool_tevent_job_done() - which does: 225 TALLOC_FREE(state->tctx); calling tevent_threaded_context_destructor(): 384 ret = pthread_mutex_destroy(&tctx->event_ctx_mutex); <---------------- BOOM returns an error ! 385 if (ret != 0) { 386 abort(); 387 } as we haven't gotten to line 481 above (the line after HERE!!!!) so the tctx->event_ctx_mutex is still locked when we try to destroy it. So doing an additional: ret = pthread_mutex_lock(&tctx->event_ctx_mutex); ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); (error checking elided) forces tevent_threaded_context_destructor() to wait until tctx->event_ctx_mutex is unlocked before it locks/unlocks and then is guaranteed safe to destroy. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Reviewed-by: Stefan Metzmacher (cherry picked from commit 1fe7ec237a7036d76764ef1981de6b3000b2cfd3) --- lib/tevent/tevent_threads.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c index 8ecda02..4d1a880 100644 --- a/lib/tevent/tevent_threads.c +++ b/lib/tevent/tevent_threads.c @@ -381,6 +381,23 @@ static int tevent_threaded_context_destructor( DLIST_REMOVE(tctx->event_ctx->threaded_contexts, tctx); } + /* + * We have to coordinate with _tevent_threaded_schedule_immediate's + * unlock of the event_ctx_mutex. We're in the main thread here, + * and we can be scheduled before the helper thread finalizes its + * call _tevent_threaded_schedule_immediate. This means we would + * pthreadpool_destroy a locked mutex, which is illegal. + */ + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + ret = pthread_mutex_destroy(&tctx->event_ctx_mutex); if (ret != 0) { abort(); -- 1.9.1 From 60ff7995dabb20dce32c534334326c376d479fd0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 17 Jun 2017 21:26:27 +0200 Subject: [PATCH 09/17] tevent: Simplify create_immediate Not much change, just 9 lines less of code. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit a7504f555eff101a10ded653ceac98d8294c1659) --- lib/tevent/tevent.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index f3b18a1..5f44b03 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -616,16 +616,7 @@ struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, im = talloc(mem_ctx, struct tevent_immediate); if (im == NULL) return NULL; - im->prev = NULL; - im->next = NULL; - im->event_ctx = NULL; - im->create_location = location; - im->handler = NULL; - im->private_data = NULL; - im->handler_name = NULL; - im->schedule_location = NULL; - im->cancel_fn = NULL; - im->additional_data = NULL; + *im = (struct tevent_immediate) { .create_location = location }; return im; } -- 1.9.1 From 7f41adaf822b4b2fe597f0d4ad6d97ab10f12dd7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 14 Jun 2017 16:59:10 +0200 Subject: [PATCH 10/17] tevent: include the finish location in tevent_req_default_print() It's verify useful when debugging code without a debugger to be able to use tevent_req_print() in DEBUG statements. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit d7f649b7044a5579d321cc1cfa7893a8221f6412) --- lib/tevent/tevent_req.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index e309c3d..22f7a4f 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -31,14 +31,15 @@ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) { return talloc_asprintf(mem_ctx, "tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] " - " state[%s (%p)] timer[%p]", + " state[%s (%p)] timer[%p] finish[%s]", req, req->internal.create_location, req->internal.state, (unsigned long long)req->internal.error, (unsigned long long)req->internal.error, talloc_get_name(req->data), req->data, - req->internal.timer + req->internal.timer, + req->internal.finish_location ); } -- 1.9.1 From dc09cdf7bca87e9ac8e6d4850a80e104e528fcc2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 20 Jun 2017 12:17:32 +0200 Subject: [PATCH 11/17] tevent: version 0.9.32 * Fix mutex locking in tevent_threaded_context_destructor(). * Fix a memleak on FreeBSD. * Re-init threading in tevent_re_initialise(). * Include the finish location in tevent_req_default_print(). Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Thu Jun 22 17:17:33 CEST 2017 on sn-devel-144 (cherry picked from commit e9b4978a764839a142d9f7c166db436bdabea82c) --- lib/tevent/ABI/tevent-0.9.32.sigs | 99 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.32.sigs diff --git a/lib/tevent/ABI/tevent-0.9.32.sigs b/lib/tevent/ABI/tevent-0.9.32.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.32.sigs @@ -0,0 +1,99 @@ +_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *) +_tevent_loop_once: int (struct tevent_context *, const char *) +_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *) +_tevent_loop_wait: int (struct tevent_context *, const char *) +_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *) +_tevent_req_callback_data: void *(struct tevent_req *) +_tevent_req_cancel: bool (struct tevent_req *, const char *) +_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *) +_tevent_req_data: void *(struct tevent_req *) +_tevent_req_done: void (struct tevent_req *, const char *) +_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *) +_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *) +_tevent_req_notify_callback: void (struct tevent_req *, const char *) +_tevent_req_oom: void (struct tevent_req *, const char *) +_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +_tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_backend_list: const char **(TALLOC_CTX *) +tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *) +tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_check_signal: int (struct tevent_context *) +tevent_common_context_destructor: int (struct tevent_context *) +tevent_common_fd_destructor: int (struct tevent_fd *) +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_loop_immediate: bool (struct tevent_context *) +tevent_common_loop_timer_delay: struct timeval (struct tevent_context *) +tevent_common_loop_wait: int (struct tevent_context *, const char *) +tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +tevent_context_init: struct tevent_context *(TALLOC_CTX *) +tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *) +tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_set_auto_close: void (struct tevent_fd *) +tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t) +tevent_fd_set_flags: void (struct tevent_fd *, uint16_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (void) +tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_length: size_t (struct tevent_queue *) +tevent_queue_running: bool (struct tevent_queue *) +tevent_queue_start: void (struct tevent_queue *) +tevent_queue_stop: void (struct tevent_queue *) +tevent_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *) +tevent_re_initialise: int (struct tevent_context *) +tevent_register_backend: bool (const char *, const struct tevent_ops *) +tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *) +tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *) +tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *) +tevent_req_is_in_progress: bool (struct tevent_req *) +tevent_req_poll: bool (struct tevent_req *, struct tevent_context *) +tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *) +tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: void (struct tevent_req *) +tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *) +tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn) +tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn) +tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +tevent_sa_info_queue_count: size_t (void) +tevent_set_abort_fn: void (void (*)(const char *)) +tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *) +tevent_set_debug_stderr: int (struct tevent_context *) +tevent_set_default_backend: void (const char *) +tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t) +tevent_timeval_compare: int (const struct timeval *, const struct timeval *) +tevent_timeval_current: struct timeval (void) +tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t) +tevent_timeval_is_zero: bool (const struct timeval *) +tevent_timeval_set: struct timeval (uint32_t, uint32_t) +tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *) +tevent_timeval_zero: struct timeval (void) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/wscript b/lib/tevent/wscript index 580ca4d..2ac9518 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.31' +VERSION = '0.9.32' blddir = 'bin' -- 1.9.1 From 2c3314e66a39bf338221f7a4818b47973c01a02b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 20 Jul 2017 14:16:44 +0200 Subject: [PATCH 12/17] tevent: avoid calling talloc_get_name(NULL) in tevent_req_default_print() We have the same information available under req->internal.private_type. This way it's possible to call tevent_req_print() after tevent_req_received() was called. Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 21b56ffd983cc0b982bea55866bfa84c79133503) (cherry picked from commit 3d87c0660eba61ac4b02e43798aa82ee9e64b454) --- lib/tevent/tevent_req.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 22f7a4f..155746e 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -36,7 +36,7 @@ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) req->internal.state, (unsigned long long)req->internal.error, (unsigned long long)req->internal.error, - talloc_get_name(req->data), + req->internal.private_type, req->data, req->internal.timer, req->internal.finish_location -- 1.9.1 From 1dfafd6959bb914f201f2052a8ada8f1b0d92798 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 20 Jul 2017 14:20:03 +0200 Subject: [PATCH 13/17] tevent: handle passing req = NULL to tevent_req_print() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit ca3e98488a45aa143e4ba454b4ba8763f09a6f50) (cherry picked from commit ce417f5ceec42a70ab651bc3a0dc2ab29cb7efd2) --- lib/tevent/tevent_req.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 155746e..15754d3 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -45,6 +45,10 @@ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) { + if (req == NULL) { + return talloc_strdup(mem_ctx, "tevent_req[NULL]"); + } + if (!req->private_print) { return tevent_req_default_print(req, mem_ctx); } -- 1.9.1 From 609c293fbdb6aa0da72b94e392b7d6c40e011df0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 21 Jul 2017 14:34:59 +0200 Subject: [PATCH 14/17] tevent: version 0.9.33 * make tevent_req_print() more robust against crashes Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 7ad3a99d462e4a43c9f64b0877111d5e58f56e6e) Autobuild-User(v4-7-test): Stefan Metzmacher Autobuild-Date(v4-7-test): Sun Jul 23 14:41:25 CEST 2017 on sn-devel-144 (cherry picked from commit 892c3aaeb683f2ed51a60ac49fc2c2ea4dede6e8) --- lib/tevent/ABI/tevent-0.9.33.sigs | 99 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.33.sigs diff --git a/lib/tevent/ABI/tevent-0.9.33.sigs b/lib/tevent/ABI/tevent-0.9.33.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.33.sigs @@ -0,0 +1,99 @@ +_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *) +_tevent_loop_once: int (struct tevent_context *, const char *) +_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *) +_tevent_loop_wait: int (struct tevent_context *, const char *) +_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *) +_tevent_req_callback_data: void *(struct tevent_req *) +_tevent_req_cancel: bool (struct tevent_req *, const char *) +_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *) +_tevent_req_data: void *(struct tevent_req *) +_tevent_req_done: void (struct tevent_req *, const char *) +_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *) +_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *) +_tevent_req_notify_callback: void (struct tevent_req *, const char *) +_tevent_req_oom: void (struct tevent_req *, const char *) +_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +_tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_backend_list: const char **(TALLOC_CTX *) +tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *) +tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_check_signal: int (struct tevent_context *) +tevent_common_context_destructor: int (struct tevent_context *) +tevent_common_fd_destructor: int (struct tevent_fd *) +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_loop_immediate: bool (struct tevent_context *) +tevent_common_loop_timer_delay: struct timeval (struct tevent_context *) +tevent_common_loop_wait: int (struct tevent_context *, const char *) +tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +tevent_context_init: struct tevent_context *(TALLOC_CTX *) +tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *) +tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_set_auto_close: void (struct tevent_fd *) +tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t) +tevent_fd_set_flags: void (struct tevent_fd *, uint16_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (void) +tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_length: size_t (struct tevent_queue *) +tevent_queue_running: bool (struct tevent_queue *) +tevent_queue_start: void (struct tevent_queue *) +tevent_queue_stop: void (struct tevent_queue *) +tevent_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *) +tevent_re_initialise: int (struct tevent_context *) +tevent_register_backend: bool (const char *, const struct tevent_ops *) +tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *) +tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *) +tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *) +tevent_req_is_in_progress: bool (struct tevent_req *) +tevent_req_poll: bool (struct tevent_req *, struct tevent_context *) +tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *) +tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: void (struct tevent_req *) +tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *) +tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn) +tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn) +tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +tevent_sa_info_queue_count: size_t (void) +tevent_set_abort_fn: void (void (*)(const char *)) +tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *) +tevent_set_debug_stderr: int (struct tevent_context *) +tevent_set_default_backend: void (const char *) +tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t) +tevent_timeval_compare: int (const struct timeval *, const struct timeval *) +tevent_timeval_current: struct timeval (void) +tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t) +tevent_timeval_is_zero: bool (const struct timeval *) +tevent_timeval_set: struct timeval (uint32_t, uint32_t) +tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *) +tevent_timeval_zero: struct timeval (void) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/wscript b/lib/tevent/wscript index 2ac9518..c1c72b4 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.32' +VERSION = '0.9.33' blddir = 'bin' -- 1.9.1 From 1b2e88cf958a5547d90552534b5a21e0cfa6c9cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Sep 2017 12:08:38 -0700 Subject: [PATCH 15/17] lib: tevent: Remove select backend. select() is no longer useful on modern systems. Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Sat Sep 16 08:35:39 CEST 2017 on sn-devel-144 (cherry picked from commit 2a003b1a576dcbbba0d60bae90427776a5c27867) --- lib/tevent/tevent.c | 1 - lib/tevent/tevent_internal.h | 1 - lib/tevent/tevent_select.c | 280 ------------------------------------------- lib/tevent/wscript | 2 +- source3/selftest/tests.py | 2 +- source3/torture/torture.c | 10 +- 6 files changed, 7 insertions(+), 289 deletions(-) delete mode 100644 lib/tevent/tevent_select.c diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 5f44b03..a2d2003 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -128,7 +128,6 @@ static void tevent_backend_init(void) done = true; - tevent_select_init(); tevent_poll_init(); tevent_poll_mt_init(); #if defined(HAVE_EPOLL) diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index a5f1ebde..47ea39b 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -377,7 +377,6 @@ int tevent_common_check_signal(struct tevent_context *ev); void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se); bool tevent_standard_init(void); -bool tevent_select_init(void); bool tevent_poll_init(void); void tevent_poll_event_add_fd_internal(struct tevent_context *ev, struct tevent_fd *fde); diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c deleted file mode 100644 index 55dd0b6..0000000 --- a/lib/tevent/tevent_select.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - Unix SMB/CIFS implementation. - main select loop and event handling - Copyright (C) Andrew Tridgell 2003-2005 - Copyright (C) Stefan Metzmacher 2005-2009 - - ** NOTE! The following LGPL license applies to the tevent - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include "replace.h" -#include "system/filesys.h" -#include "system/select.h" -#include "tevent.h" -#include "tevent_util.h" -#include "tevent_internal.h" - -struct select_event_context { - /* a pointer back to the generic event_context */ - struct tevent_context *ev; - - /* the maximum file descriptor number in fd_events */ - int maxfd; -}; - -/* - create a select_event_context structure. -*/ -static int select_event_context_init(struct tevent_context *ev) -{ - struct select_event_context *select_ev; - - /* - * We might be called during tevent_re_initialise() - * which means we need to free our old additional_data. - */ - TALLOC_FREE(ev->additional_data); - - select_ev = talloc_zero(ev, struct select_event_context); - if (!select_ev) return -1; - select_ev->ev = ev; - - ev->additional_data = select_ev; - return 0; -} - -/* - recalculate the maxfd -*/ -static void calc_maxfd(struct select_event_context *select_ev) -{ - struct tevent_fd *fde; - - select_ev->maxfd = 0; - for (fde = select_ev->ev->fd_events; fde; fde = fde->next) { - if (fde->fd > select_ev->maxfd) { - select_ev->maxfd = fde->fd; - } - } -} - - -/* to mark the ev->maxfd invalid - * this means we need to recalculate it - */ -#define EVENT_INVALID_MAXFD (-1) - -/* - destroy an fd_event -*/ -static int select_event_fd_destructor(struct tevent_fd *fde) -{ - struct tevent_context *ev = fde->event_ctx; - struct select_event_context *select_ev = NULL; - - if (ev) { - select_ev = talloc_get_type_abort(ev->additional_data, - struct select_event_context); - - if (select_ev->maxfd == fde->fd) { - select_ev->maxfd = EVENT_INVALID_MAXFD; - } - } - - return tevent_common_fd_destructor(fde); -} - -/* - add a fd based event - return NULL on failure (memory allocation error) -*/ -static struct tevent_fd *select_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, - tevent_fd_handler_t handler, - void *private_data, - const char *handler_name, - const char *location) -{ - struct select_event_context *select_ev = - talloc_get_type_abort(ev->additional_data, - struct select_event_context); - struct tevent_fd *fde; - - if (fd < 0 || fd >= FD_SETSIZE) { - errno = EBADF; - return NULL; - } - - fde = tevent_common_add_fd(ev, mem_ctx, fd, flags, - handler, private_data, - handler_name, location); - if (!fde) return NULL; - - if ((select_ev->maxfd != EVENT_INVALID_MAXFD) - && (fde->fd > select_ev->maxfd)) { - select_ev->maxfd = fde->fd; - } - talloc_set_destructor(fde, select_event_fd_destructor); - - return fde; -} - -/* - event loop handling using select() -*/ -static int select_event_loop_select(struct select_event_context *select_ev, struct timeval *tvalp) -{ - fd_set r_fds, w_fds; - struct tevent_fd *fde; - int selrtn; - int select_errno; - - /* we maybe need to recalculate the maxfd */ - if (select_ev->maxfd == EVENT_INVALID_MAXFD) { - calc_maxfd(select_ev); - } - - FD_ZERO(&r_fds); - FD_ZERO(&w_fds); - - /* setup any fd events */ - for (fde = select_ev->ev->fd_events; fde; fde = fde->next) { - if (fde->fd < 0 || fde->fd >= FD_SETSIZE) { - tevent_debug(select_ev->ev, TEVENT_DEBUG_FATAL, - "ERROR: EBADF fd[%d] >= %d " - "select_event_loop_once\n", - fde->fd, FD_SETSIZE); - errno = EBADF; - return -1; - } - - if (fde->flags & TEVENT_FD_READ) { - FD_SET(fde->fd, &r_fds); - } - if (fde->flags & TEVENT_FD_WRITE) { - FD_SET(fde->fd, &w_fds); - } - } - - if (select_ev->ev->signal_events && - tevent_common_check_signal(select_ev->ev)) { - return 0; - } - - tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_BEFORE_WAIT); - selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); - select_errno = errno; - tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_AFTER_WAIT); - - if (selrtn == -1 && select_errno == EINTR && - select_ev->ev->signal_events) { - tevent_common_check_signal(select_ev->ev); - return 0; - } - - if (selrtn == -1 && select_errno == EBADF) { - /* the socket is dead! this should never - happen as the socket should have first been - made readable and that should have removed - the event, so this must be a bug. This is a - fatal error. */ - tevent_debug(select_ev->ev, TEVENT_DEBUG_FATAL, - "ERROR: EBADF on select_event_loop_once\n"); - errno = select_errno; - return -1; - } - - if (selrtn == 0 && tvalp) { - /* we don't care about a possible delay here */ - tevent_common_loop_timer_delay(select_ev->ev); - return 0; - } - - if (selrtn > 0) { - /* at least one file descriptor is ready - check - which ones and call the handler, being careful to allow - the handler to remove itself when called */ - for (fde = select_ev->ev->fd_events; fde; fde = fde->next) { - uint16_t flags = 0; - - if (FD_ISSET(fde->fd, &r_fds) && (fde->flags & TEVENT_FD_READ)) { - flags |= TEVENT_FD_READ; - } - if (FD_ISSET(fde->fd, &w_fds) && (fde->flags & TEVENT_FD_WRITE)) { - flags |= TEVENT_FD_WRITE; - } - if (flags) { - DLIST_DEMOTE(select_ev->ev->fd_events, fde); - fde->handler(select_ev->ev, fde, flags, fde->private_data); - break; - } - } - } - - return 0; -} - -/* - do a single event loop using the events defined in ev -*/ -static int select_event_loop_once(struct tevent_context *ev, const char *location) -{ - struct select_event_context *select_ev = - talloc_get_type_abort(ev->additional_data, - struct select_event_context); - struct timeval tval; - - if (ev->signal_events && - tevent_common_check_signal(ev)) { - return 0; - } - - if (ev->threaded_contexts != NULL) { - tevent_common_threaded_activate_immediate(ev); - } - - if (ev->immediate_events && - tevent_common_loop_immediate(ev)) { - return 0; - } - - tval = tevent_common_loop_timer_delay(ev); - if (tevent_timeval_is_zero(&tval)) { - return 0; - } - - return select_event_loop_select(select_ev, &tval); -} - -static const struct tevent_ops select_event_ops = { - .context_init = select_event_context_init, - .add_fd = select_event_add_fd, - .set_fd_close_fn = tevent_common_fd_set_close_fn, - .get_fd_flags = tevent_common_fd_get_flags, - .set_fd_flags = tevent_common_fd_set_flags, - .add_timer = tevent_common_add_timer_v2, - .schedule_immediate = tevent_common_schedule_immediate, - .add_signal = tevent_common_add_signal, - .loop_once = select_event_loop_once, - .loop_wait = tevent_common_loop_wait, -}; - -_PRIVATE_ bool tevent_select_init(void) -{ - return tevent_register_backend("select", &select_event_ops); -} diff --git a/lib/tevent/wscript b/lib/tevent/wscript index c1c72b4..721c050 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -82,7 +82,7 @@ def build(bld): bld.RECURSE('lib/talloc') SRC = '''tevent.c tevent_debug.c tevent_fd.c tevent_immediate.c - tevent_queue.c tevent_req.c tevent_select.c + tevent_queue.c tevent_req.c tevent_poll.c tevent_threads.c tevent_signal.c tevent_standard.c tevent_timed.c tevent_util.c tevent_wakeup.c''' diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index b877d47..fbd9a69 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -128,7 +128,7 @@ local_tests = [ "LOCAL-sid_to_string", "LOCAL-binary_to_sid", "LOCAL-DBTRANS", - "LOCAL-TEVENT-SELECT", + "LOCAL-TEVENT-POLL", "LOCAL-CONVERT-STRING", "LOCAL-CONV-AUTH-INFO", "LOCAL-IDMAP-TDB-COMMON", diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 60e9247..015ea37 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -10910,17 +10910,17 @@ static bool run_local_dbtrans(int dummy) /* * Just a dummy test to be run under a debugger. There's no real way - * to inspect the tevent_select specific function from outside of - * tevent_select.c. + * to inspect the tevent_poll specific function from outside of + * tevent_poll.c. */ -static bool run_local_tevent_select(int dummy) +static bool run_local_tevent_poll(int dummy) { struct tevent_context *ev; struct tevent_fd *fd1, *fd2; bool result = false; - ev = tevent_context_init_byname(NULL, "select"); + ev = tevent_context_init_byname(NULL, "poll"); if (ev == NULL) { d_fprintf(stderr, "tevent_context_init_byname failed\n"); goto fail; @@ -11471,7 +11471,7 @@ static struct { { "LOCAL-sid_to_string", run_local_sid_to_string, 0}, { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0}, { "LOCAL-DBTRANS", run_local_dbtrans, 0}, - { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0}, + { "LOCAL-TEVENT-POLL", run_local_tevent_poll, 0}, { "LOCAL-CONVERT-STRING", run_local_convert_string, 0}, { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0}, { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0}, -- 1.9.1 From f0d71c4c073e8ffdbd579f2f2dd9037df084982f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Nov 2017 21:22:26 +0100 Subject: [PATCH 16/17] tevent: Fix a race condition We can't rely on tctx to exist after we unlocked the mutex. It took a while, but this does lead to data corruption. If *tctx is replaced with something where tctx->wakeup_fd points to a real, existing file descriptor, we're screwed. And by screwed, this means file corruption on disk. Again. I am not tall enough for this business. http://bholley.net/blog/2015/must-be-this-tall-to-write-multi-threaded-code.html BUG: https://bugzilla.samba.org/show_bug.cgi?id=13130 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Sat Nov 11 03:20:09 CET 2017 on sn-devel-144 (cherry picked from commit 20cfcb7dbc5dd099384b76a76e3d35cf627100b6) Autobuild-User(v4-7-test): Karolin Seeger Autobuild-Date(v4-7-test): Mon Nov 13 13:54:56 CET 2017 on sn-devel-144 (cherry picked from commit 5ec68b2e44e5c0c4e6fae362c7e36ad99124faa8) --- lib/tevent/tevent_threads.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c index 4d1a880..2e83f1b 100644 --- a/lib/tevent/tevent_threads.c +++ b/lib/tevent/tevent_threads.c @@ -451,7 +451,7 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, { #ifdef HAVE_PTHREAD struct tevent_context *ev; - int ret; + int ret, wakeup_fd; ret = pthread_mutex_lock(&tctx->event_ctx_mutex); if (ret != 0) { @@ -495,6 +495,8 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, abort(); } + wakeup_fd = tctx->wakeup_fd; + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); if (ret != 0) { abort(); @@ -510,7 +512,7 @@ void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, * than a noncontended one. So I'd opt for the lower footprint * initially. Maybe we have to change that later. */ - tevent_common_wakeup_fd(tctx->wakeup_fd); + tevent_common_wakeup_fd(wakeup_fd); #else /* * tevent_threaded_context_create() returned NULL with ENOSYS... -- 1.9.1 From 955596b440f3cb934f9ddf60e3858a7ec703b49e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Nov 2017 11:05:04 +0100 Subject: [PATCH 17/17] tevent: version 0.9.34 * Remove unused select backend * Fix a race condition in tevent_threaded_schedule_immediate() (bug #13130) Signed-off-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Mon Nov 13 18:02:46 CET 2017 on sn-devel-144 (cherry picked from commit 2e573eead96b2e98dd8a15c9c8e470679e530392) --- lib/tevent/ABI/tevent-0.9.34.sigs | 99 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.34.sigs diff --git a/lib/tevent/ABI/tevent-0.9.34.sigs b/lib/tevent/ABI/tevent-0.9.34.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.34.sigs @@ -0,0 +1,99 @@ +_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *) +_tevent_loop_once: int (struct tevent_context *, const char *) +_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *) +_tevent_loop_wait: int (struct tevent_context *, const char *) +_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *) +_tevent_req_callback_data: void *(struct tevent_req *) +_tevent_req_cancel: bool (struct tevent_req *, const char *) +_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *) +_tevent_req_data: void *(struct tevent_req *) +_tevent_req_done: void (struct tevent_req *, const char *) +_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *) +_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *) +_tevent_req_notify_callback: void (struct tevent_req *, const char *) +_tevent_req_oom: void (struct tevent_req *, const char *) +_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +_tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_backend_list: const char **(TALLOC_CTX *) +tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *) +tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) +tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) +tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *) +tevent_common_check_signal: int (struct tevent_context *) +tevent_common_context_destructor: int (struct tevent_context *) +tevent_common_fd_destructor: int (struct tevent_fd *) +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_loop_immediate: bool (struct tevent_context *) +tevent_common_loop_timer_delay: struct timeval (struct tevent_context *) +tevent_common_loop_wait: int (struct tevent_context *, const char *) +tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +tevent_context_init: struct tevent_context *(TALLOC_CTX *) +tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *) +tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_set_auto_close: void (struct tevent_fd *) +tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t) +tevent_fd_set_flags: void (struct tevent_fd *, uint16_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (void) +tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *) +tevent_queue_length: size_t (struct tevent_queue *) +tevent_queue_running: bool (struct tevent_queue *) +tevent_queue_start: void (struct tevent_queue *) +tevent_queue_stop: void (struct tevent_queue *) +tevent_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *) +tevent_re_initialise: int (struct tevent_context *) +tevent_register_backend: bool (const char *, const struct tevent_ops *) +tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *) +tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *) +tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *) +tevent_req_is_in_progress: bool (struct tevent_req *) +tevent_req_poll: bool (struct tevent_req *, struct tevent_context *) +tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *) +tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: void (struct tevent_req *) +tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *) +tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn) +tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn) +tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval) +tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn) +tevent_sa_info_queue_count: size_t (void) +tevent_set_abort_fn: void (void (*)(const char *)) +tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *) +tevent_set_debug_stderr: int (struct tevent_context *) +tevent_set_default_backend: void (const char *) +tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t) +tevent_timeval_compare: int (const struct timeval *, const struct timeval *) +tevent_timeval_current: struct timeval (void) +tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t) +tevent_timeval_is_zero: bool (const struct timeval *) +tevent_timeval_set: struct timeval (uint32_t, uint32_t) +tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *) +tevent_timeval_zero: struct timeval (void) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/wscript b/lib/tevent/wscript index 721c050..f9ff3fa 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.33' +VERSION = '0.9.34' blddir = 'bin' -- 1.9.1