The Samba-Bugzilla – Attachment 11919 Details for
Bug 11771
Backport tevent-0.9.28 changes
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.3 backported from master
v43-tevent.patch (text/plain), 70.96 KB, created by
Ralph Böhme
on 2016-03-14 14:29:32 UTC
(
hide
)
Description:
Patch for 4.3 backported from master
Filename:
MIME Type:
Creator:
Ralph Böhme
Created:
2016-03-14 14:29:32 UTC
Size:
70.96 KB
patch
obsolete
>From 229139c3fff443bfd2a56cd90184c2775f8a3dac Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 23 Jul 2015 15:23:50 -0700 >Subject: [PATCH 01/14] lib: tevent: Initial checkin of threaded tevent context > calling code. > >Adds 2 new functions: > >struct tevent_thread_proxy *tevent_thread_proxy_create( > struct tevent_context *dest_ev_ctx); > >void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, > struct tevent_immediate **pp_im, > tevent_immediate_handler_t handler, > void *pp_private_data); > >Brief doc included. Tests, docs and tutorial to follow. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 49bddd8e4756ef52b05b850aec4864749fcf31cb) >--- > lib/tevent/tevent.h | 52 +++++++ > lib/tevent/tevent_threads.c | 370 ++++++++++++++++++++++++++++++++++++++++++++ > lib/tevent/wscript | 2 +- > 3 files changed, 423 insertions(+), 1 deletion(-) > create mode 100644 lib/tevent/tevent_threads.c > >diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h >index b6c39d1..cb95507 100644 >--- a/lib/tevent/tevent.h >+++ b/lib/tevent/tevent.h >@@ -39,6 +39,7 @@ struct tevent_fd; > struct tevent_timer; > struct tevent_immediate; > struct tevent_signal; >+struct tevent_thread_proxy; > > /** > * @defgroup tevent The tevent API >@@ -1698,6 +1699,57 @@ typedef int (*tevent_nesting_hook)(struct tevent_context *ev, > bool begin, > void *stack_ptr, > const char *location); >+ >+/** >+ * @brief Create a tevent_thread_proxy for message passing between threads. >+ * >+ * The tevent_context must have been allocated on the NULL >+ * talloc context, and talloc_disable_null_tracking() must >+ * have been called. >+ * >+ * @param[in] dest_ev_ctx The tevent_context to receive events. >+ * >+ * @return An allocated tevent_thread_proxy, NULL on error. >+ * If tevent was compiled without PTHREAD support >+ * NULL is always returned and errno set to ENOSYS. >+ * >+ * @see tevent_thread_proxy_schedule() >+ */ >+struct tevent_thread_proxy *tevent_thread_proxy_create( >+ struct tevent_context *dest_ev_ctx); >+ >+/** >+ * @brief Schedule an immediate event on an event context from another thread. >+ * >+ * Causes dest_ev_ctx, being run by another thread, to receive an >+ * immediate event calling the handler with the *pp_private parameter. >+ * >+ * *pp_im must be a pointer to an immediate event talloced on a context owned >+ * by the calling thread, or the NULL context. Ownership will >+ * be transferred to the tevent_thread_proxy and *pp_im will be returned as NULL. >+ * >+ * *pp_private_data must be a talloced area of memory with no destructors. >+ * Ownership of this memory will be transferred to the tevent library and >+ * *pp_private_data will be set to NULL on successful completion of >+ * the call. Set pp_private to NULL if no parameter transfer >+ * needed (a pure callback). This is an asynchronous request, caller >+ * does not wait for callback to be completed before returning. >+ * >+ * @param[in] tp The tevent_thread_proxy to use. >+ * >+ * @param[in] pp_im Pointer to immediate event pointer. >+ * >+ * @param[in] handler The function that will be called. >+ * >+ * @param[in] pp_private_data The talloced memory to transfer. >+ * >+ * @see tevent_thread_proxy_create() >+ */ >+void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, >+ struct tevent_immediate **pp_im, >+ tevent_immediate_handler_t handler, >+ void *pp_private_data); >+ > #ifdef TEVENT_DEPRECATED > #ifndef _DEPRECATED_ > #if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) >diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c >new file mode 100644 >index 0000000..8d44e4f >--- /dev/null >+++ b/lib/tevent/tevent_threads.c >@@ -0,0 +1,370 @@ >+/* >+ tevent event library. >+ >+ Copyright (C) Jeremy Allison 2015 >+ >+ ** 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 <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "replace.h" >+#include "system/filesys.h" >+#include "talloc.h" >+#include "tevent.h" >+#include "tevent_internal.h" >+#include "tevent_util.h" >+ >+#if defined(HAVE_PTHREAD) >+#include <pthread.h> >+ >+struct tevent_immediate_list { >+ struct tevent_immediate_list *next, *prev; >+ tevent_immediate_handler_t handler; >+ struct tevent_immediate *im; >+ void *private_ptr; >+}; >+ >+struct tevent_thread_proxy { >+ pthread_mutex_t mutex; >+ struct tevent_context *dest_ev_ctx; >+ int read_fd; >+ int write_fd; >+ struct tevent_fd *pipe_read_fde; >+ /* Pending events list. */ >+ struct tevent_immediate_list *im_list; >+ /* Completed events list. */ >+ struct tevent_immediate_list *tofree_im_list; >+ struct tevent_immediate *free_im; >+}; >+ >+static void free_im_list(struct tevent_immediate_list **pp_list_head) >+{ >+ struct tevent_immediate_list *im_entry = NULL; >+ struct tevent_immediate_list *im_next = NULL; >+ >+ for (im_entry = *pp_list_head; im_entry; im_entry = im_next) { >+ im_next = im_entry->next; >+ DLIST_REMOVE(*pp_list_head, im_entry); >+ TALLOC_FREE(im_entry); >+ } >+} >+ >+static void free_list_handler(struct tevent_context *ev, >+ struct tevent_immediate *im, >+ void *private_ptr) >+{ >+ struct tevent_thread_proxy *tp = >+ talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); >+ int ret; >+ >+ ret = pthread_mutex_lock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return; >+ } >+ >+ free_im_list(&tp->tofree_im_list); >+ >+ ret = pthread_mutex_unlock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return; >+ } >+} >+ >+static void schedule_immediate_functions(struct tevent_thread_proxy *tp) >+{ >+ struct tevent_immediate_list *im_entry = NULL; >+ struct tevent_immediate_list *im_next = NULL; >+ >+ for (im_entry = tp->im_list; im_entry; im_entry = im_next) { >+ im_next = im_entry->next; >+ DLIST_REMOVE(tp->im_list, im_entry); >+ >+ tevent_schedule_immediate(im_entry->im, >+ tp->dest_ev_ctx, >+ im_entry->handler, >+ im_entry->private_ptr); >+ >+ /* Move from pending list to free list. */ >+ DLIST_ADD(tp->tofree_im_list, im_entry); >+ } >+ if (tp->tofree_im_list != NULL) { >+ /* >+ * Once the current immediate events >+ * are processed, we need to reshedule >+ * ourselves to free them. This works >+ * as tevent_schedule_immediate() >+ * always adds events to the *END* of >+ * the immediate events list. >+ */ >+ tevent_schedule_immediate(tp->free_im, >+ tp->dest_ev_ctx, >+ free_list_handler, >+ tp); >+ } >+} >+ >+static void pipe_read_handler(struct tevent_context *ev, >+ struct tevent_fd *fde, >+ uint16_t flags, >+ void *private_ptr) >+{ >+ struct tevent_thread_proxy *tp = >+ talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); >+ ssize_t len = 64; >+ int ret; >+ >+ ret = pthread_mutex_lock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return; >+ } >+ >+ /* >+ * Clear out all data in the pipe. We >+ * don't really care if this returns -1. >+ */ >+ while (len == 64) { >+ char buf[64]; >+ len = read(tp->read_fd, buf, 64); >+ }; >+ >+ schedule_immediate_functions(tp); >+ >+ ret = pthread_mutex_unlock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return; >+ } >+} >+ >+static int tevent_thread_proxy_destructor(struct tevent_thread_proxy *tp) >+{ >+ int ret; >+ >+ ret = pthread_mutex_lock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return 0; >+ } >+ >+ TALLOC_FREE(tp->pipe_read_fde); >+ >+ if (tp->read_fd != -1) { >+ (void)close(tp->read_fd); >+ tp->read_fd = -1; >+ } >+ if (tp->write_fd != -1) { >+ (void)close(tp->write_fd); >+ tp->write_fd = -1; >+ } >+ >+ /* Hmmm. It's probably an error if we get here with >+ any non-NULL immediate entries.. */ >+ >+ free_im_list(&tp->im_list); >+ free_im_list(&tp->tofree_im_list); >+ >+ TALLOC_FREE(tp->free_im); >+ >+ ret = pthread_mutex_unlock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return 0; >+ } >+ >+ ret = pthread_mutex_destroy(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return 0; >+ } >+ >+ return 0; >+} >+ >+/* >+ * Create a struct that can be passed to other threads >+ * to allow them to signal the struct tevent_context * >+ * passed in. >+ */ >+ >+struct tevent_thread_proxy *tevent_thread_proxy_create( >+ struct tevent_context *dest_ev_ctx) >+{ >+ int ret; >+ int pipefds[2]; >+ struct tevent_thread_proxy *tp; >+ >+ tp = talloc_zero(dest_ev_ctx, struct tevent_thread_proxy); >+ if (tp == NULL) { >+ return NULL; >+ } >+ >+ ret = pthread_mutex_init(&tp->mutex, NULL); >+ if (ret != 0) { >+ goto fail; >+ } >+ >+ tp->dest_ev_ctx = dest_ev_ctx; >+ tp->read_fd = -1; >+ tp->write_fd = -1; >+ >+ talloc_set_destructor(tp, tevent_thread_proxy_destructor); >+ >+ ret = pipe(pipefds); >+ if (ret == -1) { >+ goto fail; >+ } >+ >+ tp->read_fd = pipefds[0]; >+ tp->write_fd = pipefds[1]; >+ >+ ret = ev_set_blocking(pipefds[0], false); >+ if (ret != 0) { >+ goto fail; >+ } >+ ret = ev_set_blocking(pipefds[1], false); >+ if (ret != 0) { >+ goto fail; >+ } >+ if (!ev_set_close_on_exec(pipefds[0])) { >+ goto fail; >+ } >+ if (!ev_set_close_on_exec(pipefds[1])) { >+ goto fail; >+ } >+ >+ tp->pipe_read_fde = tevent_add_fd(dest_ev_ctx, >+ tp, >+ tp->read_fd, >+ TEVENT_FD_READ, >+ pipe_read_handler, >+ tp); >+ if (tp->pipe_read_fde == NULL) { >+ goto fail; >+ } >+ >+ /* >+ * Create an immediate event to free >+ * completed lists. >+ */ >+ tp->free_im = tevent_create_immediate(tp); >+ if (tp->free_im == NULL) { >+ goto fail; >+ } >+ >+ return tp; >+ >+ fail: >+ >+ TALLOC_FREE(tp); >+ return NULL; >+} >+ >+/* >+ * This function schedules an immediate event to be called with argument >+ * *pp_private in the thread context of dest_ev_ctx. Caller doesn't >+ * wait for activation to take place, this is simply fire-and-forget. >+ * >+ * pp_im must be a pointer to an immediate event talloced on >+ * a context owned by the calling thread, or the NULL context. >+ * Ownership of *pp_im will be transfered to the tevent library. >+ * >+ * pp_private can be null, or contents of *pp_private must be >+ * talloc'ed memory on a context owned by the calling thread >+ * or the NULL context. If non-null, ownership of *pp_private will >+ * be transfered to the tevent library. >+ * >+ * If you want to return a message, have the destination use the >+ * same function call to send back to the caller. >+ */ >+ >+ >+void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, >+ struct tevent_immediate **pp_im, >+ tevent_immediate_handler_t handler, >+ void *pp_private_data) >+{ >+ struct tevent_immediate_list *im_entry; >+ int ret; >+ char c; >+ >+ ret = pthread_mutex_lock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ return; >+ } >+ >+ if (tp->write_fd == -1) { >+ /* In the process of being destroyed. Ignore. */ >+ goto end; >+ } >+ >+ /* Create a new immediate_list entry. MUST BE ON THE NULL CONTEXT */ >+ im_entry = talloc_zero(NULL, struct tevent_immediate_list); >+ if (im_entry == NULL) { >+ goto end; >+ } >+ >+ im_entry->handler = handler; >+ im_entry->im = talloc_move(im_entry, pp_im); >+ >+ if (pp_private_data != NULL) { >+ void **pptr = (void **)pp_private_data; >+ im_entry->private_ptr = talloc_move(im_entry, pptr); >+ } >+ >+ DLIST_ADD(tp->im_list, im_entry); >+ >+ /* And notify the dest_ev_ctx to wake up. */ >+ c = '\0'; >+ (void)write(tp->write_fd, &c, 1); >+ >+ end: >+ >+ ret = pthread_mutex_unlock(&tp->mutex); >+ if (ret != 0) { >+ abort(); >+ /* Notreached. */ >+ } >+} >+#else >+/* !HAVE_PTHREAD */ >+struct tevent_thread_proxy *tevent_thread_proxy_create( >+ struct tevent_context *dest_ev_ctx) >+{ >+ errno = ENOSYS; >+ return NULL; >+} >+ >+void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, >+ struct tevent_immediate **pp_im, >+ tevent_immediate_handler_t handler, >+ void *pp_private_data) >+{ >+ ; >+} >+#endif >diff --git a/lib/tevent/wscript b/lib/tevent/wscript >index 827094c..d41e7e7 100755 >--- a/lib/tevent/wscript >+++ b/lib/tevent/wscript >@@ -83,7 +83,7 @@ def build(bld): > > SRC = '''tevent.c tevent_debug.c tevent_fd.c tevent_immediate.c > tevent_queue.c tevent_req.c tevent_select.c >- tevent_poll.c >+ tevent_poll.c tevent_threads.c > tevent_signal.c tevent_standard.c tevent_timed.c tevent_util.c tevent_wakeup.c''' > > if bld.CONFIG_SET('HAVE_EPOLL'): >-- >2.5.0 > > >From 44415fa99a1ac1cc8cc8f8e4da81576a1065a9d7 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 24 Jul 2015 08:50:31 -0700 >Subject: [PATCH 02/14] lib: tevent: Initial test of tevent threaded context > code. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 187aebb25b970a3679a72109def8e8b85622722e) >--- > lib/tevent/testsuite.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 125 insertions(+) > >diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c >index c63c878..f8f65f8 100644 >--- a/lib/tevent/testsuite.c >+++ b/lib/tevent/testsuite.c >@@ -808,6 +808,127 @@ static bool test_event_context_threaded(struct torture_context *test, > return true; > } > >+#define NUM_TEVENT_THREADS 100 >+ >+/* Ugly, but needed for torture_comment... */ >+static struct torture_context *thread_test_ctx; >+static pthread_t thread_map[NUM_TEVENT_THREADS]; >+static unsigned thread_counter; >+ >+/* Called in master thread context */ >+static void callback_nowait(struct tevent_context *ev, >+ struct tevent_immediate *im, >+ void *private_ptr) >+{ >+ pthread_t *thread_id_ptr = >+ talloc_get_type_abort(private_ptr, pthread_t); >+ unsigned i; >+ >+ for (i = 0; i < NUM_TEVENT_THREADS; i++) { >+ if (pthread_equal(*thread_id_ptr, >+ thread_map[i])) { >+ break; >+ } >+ } >+ torture_comment(thread_test_ctx, >+ "Callback %u from thread %u\n", >+ thread_counter, >+ i); >+ thread_counter++; >+} >+ >+/* Blast the master tevent_context with a callback, no waiting. */ >+static void *thread_fn_nowait(void *private_ptr) >+{ >+ struct tevent_thread_proxy *master_tp = >+ talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); >+ struct tevent_immediate *im; >+ pthread_t *thread_id_ptr; >+ >+ im = tevent_create_immediate(NULL); >+ if (im == NULL) { >+ return NULL; >+ } >+ thread_id_ptr = talloc(NULL, pthread_t); >+ if (thread_id_ptr == NULL) { >+ return NULL; >+ } >+ *thread_id_ptr = pthread_self(); >+ >+ tevent_thread_proxy_schedule(master_tp, >+ &im, >+ callback_nowait, >+ &thread_id_ptr); >+ return NULL; >+} >+ >+static void timeout_fn(struct tevent_context *ev, >+ struct tevent_timer *te, >+ struct timeval tv, void *p) >+{ >+ thread_counter = NUM_TEVENT_THREADS * 10; >+} >+ >+static bool test_multi_tevent_threaded(struct torture_context *test, >+ const void *test_data) >+{ >+ unsigned i; >+ struct tevent_context *master_ev; >+ struct tevent_thread_proxy *tp; >+ >+ talloc_disable_null_tracking(); >+ >+ /* Ugly global stuff. */ >+ thread_test_ctx = test; >+ thread_counter = 0; >+ >+ master_ev = tevent_context_init(NULL); >+ if (master_ev == NULL) { >+ return false; >+ } >+ tevent_set_debug_stderr(master_ev); >+ >+ tp = tevent_thread_proxy_create(master_ev); >+ if (tp == NULL) { >+ torture_fail(test, >+ talloc_asprintf(test, >+ "tevent_thread_proxy_create failed\n")); >+ talloc_free(master_ev); >+ return false; >+ } >+ >+ for (i = 0; i < NUM_TEVENT_THREADS; i++) { >+ int ret = pthread_create(&thread_map[i], >+ NULL, >+ thread_fn_nowait, >+ tp); >+ if (ret != 0) { >+ torture_fail(test, >+ talloc_asprintf(test, >+ "Failed to create thread %i, %d\n", >+ i, ret)); >+ return false; >+ } >+ } >+ >+ /* Ensure we don't wait more than 10 seconds. */ >+ tevent_add_timer(master_ev, >+ master_ev, >+ timeval_current_ofs(10,0), >+ timeout_fn, >+ NULL); >+ >+ while (thread_counter < NUM_TEVENT_THREADS) { >+ int ret = tevent_loop_once(master_ev); >+ torture_assert(test, ret == 0, "tevent_loop_once failed"); >+ } >+ >+ torture_assert(test, thread_counter == NUM_TEVENT_THREADS, >+ "thread_counter fail\n"); >+ >+ talloc_free(master_ev); >+ return true; >+} > #endif > > struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) >@@ -841,6 +962,10 @@ struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) > torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt", > test_event_context_threaded, > NULL); >+ >+ torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded", >+ test_multi_tevent_threaded, >+ NULL); > #endif > > return suite; >-- >2.5.0 > > >From ca03896d8cfeafbf757a7f57f0ddf2d809c929ab Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 24 Jul 2015 09:27:21 -0700 >Subject: [PATCH 03/14] lib: tevent: tests: Add a second thread test that does > request/reply. > >Both tests run cleanly with valgrind --tool=drd and >valgrind --tool=helgrind > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit a132320b4c434ae9c2188377951d092f7309e63c) >--- > lib/tevent/testsuite.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 205 insertions(+) > >diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c >index f8f65f8..bcd27fd 100644 >--- a/lib/tevent/testsuite.c >+++ b/lib/tevent/testsuite.c >@@ -929,6 +929,206 @@ static bool test_multi_tevent_threaded(struct torture_context *test, > talloc_free(master_ev); > return true; > } >+ >+struct reply_state { >+ struct tevent_thread_proxy *reply_tp; >+ pthread_t thread_id; >+ int *p_finished; >+}; >+ >+static void thread_timeout_fn(struct tevent_context *ev, >+ struct tevent_timer *te, >+ struct timeval tv, void *p) >+{ >+ int *p_finished = (int *)p; >+ >+ *p_finished = 2; >+} >+ >+/* Called in child-thread context */ >+static void thread_callback(struct tevent_context *ev, >+ struct tevent_immediate *im, >+ void *private_ptr) >+{ >+ struct reply_state *rsp = >+ talloc_get_type_abort(private_ptr, struct reply_state); >+ >+ talloc_steal(ev, rsp); >+ *rsp->p_finished = 1; >+} >+ >+/* Called in master thread context */ >+static void master_callback(struct tevent_context *ev, >+ struct tevent_immediate *im, >+ void *private_ptr) >+{ >+ struct reply_state *rsp = >+ talloc_get_type_abort(private_ptr, struct reply_state); >+ unsigned i; >+ >+ talloc_steal(ev, rsp); >+ >+ for (i = 0; i < NUM_TEVENT_THREADS; i++) { >+ if (pthread_equal(rsp->thread_id, >+ thread_map[i])) { >+ break; >+ } >+ } >+ torture_comment(thread_test_ctx, >+ "Callback %u from thread %u\n", >+ thread_counter, >+ i); >+ /* Now reply to the thread ! */ >+ tevent_thread_proxy_schedule(rsp->reply_tp, >+ &im, >+ thread_callback, >+ &rsp); >+ >+ thread_counter++; >+} >+ >+static void *thread_fn_1(void *private_ptr) >+{ >+ struct tevent_thread_proxy *master_tp = >+ talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); >+ struct tevent_thread_proxy *tp; >+ struct tevent_immediate *im; >+ struct tevent_context *ev; >+ struct reply_state *rsp; >+ int finished = 0; >+ int ret; >+ >+ ev = tevent_context_init(NULL); >+ if (ev == NULL) { >+ return NULL; >+ } >+ >+ tp = tevent_thread_proxy_create(ev); >+ if (tp == NULL) { >+ talloc_free(ev); >+ return NULL; >+ } >+ >+ im = tevent_create_immediate(ev); >+ if (im == NULL) { >+ talloc_free(ev); >+ return NULL; >+ } >+ >+ rsp = talloc(ev, struct reply_state); >+ if (rsp == NULL) { >+ talloc_free(ev); >+ return NULL; >+ } >+ >+ rsp->thread_id = pthread_self(); >+ rsp->reply_tp = tp; >+ rsp->p_finished = &finished; >+ >+ /* Introduce a little randomness into the mix.. */ >+ usleep(random() % 7000); >+ >+ tevent_thread_proxy_schedule(master_tp, >+ &im, >+ master_callback, >+ &rsp); >+ >+ /* Ensure we don't wait more than 10 seconds. */ >+ tevent_add_timer(ev, >+ ev, >+ timeval_current_ofs(10,0), >+ thread_timeout_fn, >+ &finished); >+ >+ while (finished == 0) { >+ ret = tevent_loop_once(ev); >+ assert(ret == 0); >+ } >+ >+ if (finished > 1) { >+ /* Timeout ! */ >+ abort(); >+ } >+ >+ /* >+ * NB. We should talloc_free(ev) here, but if we do >+ * we currently get hit by helgrind Fix #323432 >+ * "When calling pthread_cond_destroy or pthread_mutex_destroy >+ * with initializers as argument Helgrind (incorrectly) reports errors." >+ * >+ * http://valgrind.10908.n7.nabble.com/Helgrind-3-9-0-false-positive- >+ * with-pthread-mutex-destroy-td47757.html >+ * >+ * Helgrind doesn't understand that the request/reply >+ * messages provide synchronization between the lock/unlock >+ * in tevent_thread_proxy_schedule(), and the pthread_destroy() >+ * when the struct tevent_thread_proxy object is talloc_free'd. >+ * >+ * As a work-around for now return ev for the parent thread to free. >+ */ >+ return ev; >+} >+ >+static bool test_multi_tevent_threaded_1(struct torture_context *test, >+ const void *test_data) >+{ >+ unsigned i; >+ struct tevent_context *master_ev; >+ struct tevent_thread_proxy *master_tp; >+ int ret; >+ >+ talloc_disable_null_tracking(); >+ >+ /* Ugly global stuff. */ >+ thread_test_ctx = test; >+ thread_counter = 0; >+ >+ master_ev = tevent_context_init(NULL); >+ if (master_ev == NULL) { >+ return false; >+ } >+ tevent_set_debug_stderr(master_ev); >+ >+ master_tp = tevent_thread_proxy_create(master_ev); >+ if (master_tp == NULL) { >+ torture_fail(test, >+ talloc_asprintf(test, >+ "tevent_thread_proxy_create failed\n")); >+ talloc_free(master_ev); >+ return false; >+ } >+ >+ for (i = 0; i < NUM_TEVENT_THREADS; i++) { >+ ret = pthread_create(&thread_map[i], >+ NULL, >+ thread_fn_1, >+ master_tp); >+ if (ret != 0) { >+ torture_fail(test, >+ talloc_asprintf(test, >+ "Failed to create thread %i, %d\n", >+ i, ret)); >+ return false; >+ } >+ } >+ >+ while (thread_counter < NUM_TEVENT_THREADS) { >+ ret = tevent_loop_once(master_ev); >+ torture_assert(test, ret == 0, "tevent_loop_once failed"); >+ } >+ >+ /* Wait for all the threads to finish - join 'em. */ >+ for (i = 0; i < NUM_TEVENT_THREADS; i++) { >+ void *retval; >+ ret = pthread_join(thread_map[i], &retval); >+ torture_assert(test, ret == 0, "pthread_join failed"); >+ /* Free the child thread event context. */ >+ talloc_free(retval); >+ } >+ >+ talloc_free(master_ev); >+ return true; >+} > #endif > > struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) >@@ -966,6 +1166,11 @@ struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) > torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded", > test_multi_tevent_threaded, > NULL); >+ >+ torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_1", >+ test_multi_tevent_threaded_1, >+ NULL); >+ > #endif > > return suite; >-- >2.5.0 > > >From 15e4e1cba15adb78eec539a46669ad68d34ac32a Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 22 Jul 2015 11:52:06 -0700 >Subject: [PATCH 04/14] lib: tevent: docs: Add tutorial on thread usage. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 68077c617b0a456baea56349fbf502307318c487) >--- > lib/tevent/doc/tevent_thread.dox | 322 +++++++++++++++++++++++++++++++++++++ > lib/tevent/doc/tevent_tutorial.dox | 2 + > 2 files changed, 324 insertions(+) > create mode 100644 lib/tevent/doc/tevent_thread.dox > >diff --git a/lib/tevent/doc/tevent_thread.dox b/lib/tevent/doc/tevent_thread.dox >new file mode 100644 >index 0000000..7b45820 >--- /dev/null >+++ b/lib/tevent/doc/tevent_thread.dox >@@ -0,0 +1,322 @@ >+/** >+@page tevent_context Chapter 6: Tevent with threads >+ >+@section context Tevent with threads >+ >+In order to use tevent with threads, you must first understand >+how to use the talloc library in threaded programs. For more >+information about working with talloc, please visit <a >+href="https://talloc.samba.org/">talloc website</a> where tutorial and >+documentation are located. >+ >+If a tevent context structure is talloced from a NULL, thread-safe talloc >+context, then it can be safe to use in a threaded program. The function >+<code>talloc_disable_null_tracking()</code> <b>must</b> be called from the initial >+program thread before any talloc calls are made to ensure talloc is thread-safe. >+ >+Each thread must create it's own tevent context structure as follows >+<code>tevent_context_init(NULL)</code> and no talloc memory contexts >+can be shared between threads. >+ >+Separate threads using tevent in this way can communicate >+by writing data into file descriptors that are being monitored >+by a tevent context on another thread. For example (simplified >+with no error handling): >+ >+@code >+Main thread: >+ >+main() >+{ >+ talloc_disable_null_tracking(); >+ >+ struct tevent_context *master_ev = tevent_context_init(NULL); >+ void *mem_ctx = talloc_new(master_ev); >+ >+ // Create file descriptor to monitor. >+ int pipefds[2]; >+ >+ pipe(pipefds); >+ >+ struct tevent_fd *fde = tevent_add_fd(master_ev, >+ mem_ctx, >+ pipefds[0], // read side of pipe >+ TEVENT_FD_READ, >+ pipe_read_handler, // callback function >+ private_data_pointer); >+ >+ // Create sub thread, pass pipefds[1] write side of pipe to it. >+ // The above code not shown here.. >+ >+ // Process events. >+ tevent_loop_wait(master_ev); >+ >+ // Cleanup if loop exits. >+ talloc_free(master_ev); >+} >+ >+@endcode >+ >+When the subthread writes to pipefds[1], the function >+<code>pipe_read_handler()</code> will be called in the main thread. >+ >+@subsection More sophisticated use >+ >+A popular way to use an event library within threaded programs >+is to allow a sub-thread to asynchronously schedule a tevent_immediate >+function call from the event loop of another thread. This can be built >+out of the basic functions and isolation mechanisms of tevent, >+but tevent also comes with some utility functions that make >+this easier, so long as you understand the limitations that >+using threads with talloc and tevent impose. >+ >+To allow a tevent context to receive an asynchronous tevent_immediate >+function callback from another thread, create a struct tevent_thread_proxy * >+by calling @code >+ >+struct tevent_thread_proxy *tevent_thread_proxy_create( >+ struct tevent_context *dest_ev_ctx); >+ >+@endcode >+ >+This function allocates the internal data structures to >+allow asynchronous callbacks as a talloc child of the >+struct tevent_context *, and returns a struct tevent_thread_proxy * >+that can be passed to another thread. >+ >+When you have finished receiving asynchronous callbacks, simply >+talloc_free the struct tevent_thread_proxy *, or talloc_free >+the struct tevent_context *, which will deallocate the resources >+used. >+ >+To schedule an asynchronous tevent_immediate function call from one >+thread on the tevent loop of another thread, use >+@code >+ >+void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, >+ struct tevent_immediate **pp_im, >+ tevent_immediate_handler_t handler, >+ void **pp_private_data); >+ >+@endcode >+ >+This function causes the function <code>handler()</code> >+to be invoked as a tevent_immediate callback from the event loop >+of the thread that created the struct tevent_thread_proxy * >+(so the owning <code>struct tevent_context *</code> should be >+long-lived and not in the process of being torn down). >+ >+The <code>struct tevent_thread_proxy</code> object being >+used here is a child of the event context of the target >+thread. So external synchronization mechanisms must be >+used to ensure that the target object is still in use >+at the time of the <code>tevent_thread_proxy_schedule()</code> >+call. In the example below, the request/response nature >+of the communication ensures this. >+ >+The <code>struct tevent_immediate **pp_im</code> passed into this function >+should be a struct tevent_immediate * allocated on a talloc context >+local to this thread, and will be reparented via talloc_move >+to be owned by <code>struct tevent_thread_proxy *tp</code>. >+<code>*pp_im</code> will be set to NULL on successful scheduling >+of the tevent_immediate call. >+ >+<code>handler()</code> will be called as a normal tevent_immediate >+callback from the <code>struct tevent_context *</code> of the destination >+event loop that created the <code>struct tevent_thread_proxy *</code> >+ >+Returning from this functions does not mean that the <code>handler</code> >+has been invoked, merely that it has been scheduled to be called in the >+destination event loop. >+ >+Because the calling thread does not wait for the >+callback to be scheduled and run on the destination >+thread, this is a fire-and-forget call. If you wish >+confirmation of the <code>handler()</code> being >+successfully invoked, you must ensure it replies to the >+caller in some way. >+ >+Because of asynchronous nature of this call, the nature >+of the parameter passed to the destination thread has some >+restructions. If you don't need parameters, merely pass >+<code>NULL</code> as the value of >+<code>void **pp_private_data</code>. >+ >+If you wish to pass a pointer to data between the threads, >+it <b>MUST</b> be a pointer to a talloced pointer, which is >+not part of a talloc-pool, and it must not have a destructor >+attached. The ownership of the memory pointed to will >+be passed from the calling thread to the tevent library, >+and if the receiving thread does not talloc-reparent >+it to its own contexts, it will be freed once the >+<code>handler</code> is called. >+ >+On success, <code>*pp_private</code> will be <code>NULL</code> >+to signify the talloc memory ownership has been moved. >+ >+In practice for message passing between threads in >+event loops these restrictions are not very onerous. >+ >+The easiest way to to a request-reply pair between >+tevent loops on different threads is to pass the >+parameter block of memory back and forth using >+a reply <code>tevent_thread_proxy_schedule()</code> >+call. >+ >+Here is an example (without error checking for >+simplicity): >+ >+@code >+------------------------------------------------ >+// Master thread. >+ >+main() >+{ >+ // Make talloc thread-safe. >+ >+ talloc_disable_null_tracking(); >+ >+ // Create the master event context. >+ >+ struct tevent_context *master_ev = tevent_context_init(NULL); >+ >+ // Create the master thread proxy to allow it to receive >+ // async callbacks from other threads. >+ >+ struct tevent_thread_proxy *master_tp = >+ tevent_thread_proxy_create(master_ev); >+ >+ // Create sub-threads, passing master_tp in >+ // some way to them. >+ // This code not shown.. >+ >+ // Process events. >+ // Function master_callback() below >+ // will be invoked on this thread on >+ // master_ev event context. >+ >+ tevent_loop_wait(master_ev); >+ >+ // Cleanup if loop exits. >+ >+ talloc_free(master_ev); >+} >+ >+// Data passed between threads. >+struct reply_state { >+ struct tevent_thread_proxy *reply_tp; >+ pthread_t thread_id; >+ bool *p_finished; >+}; >+ >+// Callback Called in child thread context. >+ >+static void thread_callback(struct tevent_context *ev, >+ struct tevent_immediate *im, >+ void *private_ptr) >+{ >+ // Move the ownership of what private_ptr >+ // points to from the tevent library back to this thread. >+ >+ struct reply_state *rsp = >+ talloc_get_type_abort(private_ptr, struct reply_state); >+ >+ talloc_steal(ev, rsp); >+ >+ *rsp->p_finished = true; >+ >+ // im will be talloc_freed on return from this call. >+ // but rsp will not. >+} >+ >+// Callback Called in master thread context. >+ >+static void master_callback(struct tevent_context *ev, >+ struct tevent_immediate *im, >+ void *private_ptr) >+{ >+ // Move the ownership of what private_ptr >+ // points to from the tevent library to this thread. >+ >+ struct reply_state *rsp = >+ talloc_get_type_abort(private_ptr, struct reply_state); >+ >+ talloc_steal(ev, rsp); >+ >+ printf("Callback from thread %s\n", thread_id_to_string(rsp->thread_id)); >+ >+ /* Now reply to the thread ! */ >+ tevent_thread_proxy_schedule(rsp->reply_tp, >+ &im, >+ thread_callback, >+ &rsp); >+ >+ // Note - rsp and im are now NULL as the tevent library >+ // owns the memory. >+} >+ >+// Child thread. >+ >+static void *thread_fn(void *private_ptr) >+{ >+ struct tevent_thread_proxy *master_tp = >+ talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); >+ bool finished = false; >+ int ret; >+ >+ // Create our own event context. >+ >+ struct tevent_context *ev = tevent_context_init(NULL); >+ >+ // Create the local thread proxy to allow us to receive >+ // async callbacks from other threads. >+ >+ struct tevent_thread_proxy *local_tp = >+ tevent_thread_proxy_create(master_ev); >+ >+ // Setup the data to send. >+ >+ struct reply_state *rsp = talloc(ev, struct reply_state); >+ >+ rsp->reply_tp = local_tp; >+ rsp->thread_id = pthread_self(); >+ rsp->p_finished = &finished; >+ >+ // Create the immediate event to use. >+ >+ struct tevent_immediate *im = tevent_create_immediate(ev); >+ >+ // Call the master thread. >+ >+ tevent_thread_proxy_schedule(master_tp, >+ &im, >+ master_callback, >+ &rsp); >+ >+ // Note - rsp and im are now NULL as the tevent library >+ // owns the memory. >+ >+ // Wait for the reply. >+ >+ while (!finished) { >+ tevent_loop_once(ev); >+ } >+ >+ // Cleanup. >+ >+ talloc_free(ev); >+ return NULL; >+} >+ >+@endcode >+ >+Note this doesn't have to be a master-subthread communication. >+Any thread that has access to the <code>struct tevent_thread_proxy *</code> >+pointer of another thread that has called <code>tevent_thread_proxy_create() >+</code> can send an async tevent_immediate request. >+ >+But remember the caveat that external synchronization must be used >+to ensure the target <code>struct tevent_thread_proxy *</code> object >+exists at the time of the <code>tevent_thread_proxy_schedule()</code> >+call or unreproducible crashes will result. >+*/ >diff --git a/lib/tevent/doc/tevent_tutorial.dox b/lib/tevent/doc/tevent_tutorial.dox >index 9f01fa1..207a244 100644 >--- a/lib/tevent/doc/tevent_tutorial.dox >+++ b/lib/tevent/doc/tevent_tutorial.dox >@@ -17,4 +17,6 @@ Tutorial describing working with tevent library. > > @subpage tevent_queue > >+@subpage tevent_thread >+ > */ >-- >2.5.0 > > >From 8cd4d7ab8a3a67dbddb3c4784c1ae2c6746e41cd Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 24 Aug 2015 15:47:51 +0200 >Subject: [PATCH 05/14] tevent: version 0.9.26 > >* New tevent_thread_proxy API >* Minor build fixes > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 9884a8fa58ffc8ddff0977c069aedda3beb6415f) >--- > lib/tevent/ABI/tevent-0.9.26.sigs | 90 +++++++++++++++++++++++++++++++++++++++ > lib/tevent/wscript | 2 +- > 2 files changed, 91 insertions(+), 1 deletion(-) > create mode 100644 lib/tevent/ABI/tevent-0.9.26.sigs > >diff --git a/lib/tevent/ABI/tevent-0.9.26.sigs b/lib/tevent/ABI/tevent-0.9.26.sigs >new file mode 100644 >index 0000000..1357751 >--- /dev/null >+++ b/lib/tevent/ABI/tevent-0.9.26.sigs >@@ -0,0 +1,90 @@ >+_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_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_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_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_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_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_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 d41e7e7..4c5fe0c 100755 >--- a/lib/tevent/wscript >+++ b/lib/tevent/wscript >@@ -1,7 +1,7 @@ > #!/usr/bin/env python > > APPNAME = 'tevent' >-VERSION = '0.9.25' >+VERSION = '0.9.26' > > blddir = 'bin' > >-- >2.5.0 > > >From cd0ec0cec1efa5b203dbb691e628ebf109f637ca Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Tue, 17 Nov 2015 10:28:50 -0800 >Subject: [PATCH 06/14] lib: tevent: Fix bug in poll backend - > poll_event_loop_poll() > >If the (pfd->revents & POLLNVAL) case is triggered, >we do DLIST_REMOVE(ev->fd_events, fde); and then >use fde->next in the loop above. > >Save off fde->next for loop interation before >this so we can't use a deleted ->next value. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 2be3dd1407eabe3df360ede2eab178848e34733c) >--- > lib/tevent/tevent_poll.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > >diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c >index 573ba93..9b1781f 100644 >--- a/lib/tevent/tevent_poll.c >+++ b/lib/tevent/tevent_poll.c >@@ -498,6 +498,7 @@ static int poll_event_loop_poll(struct tevent_context *ev, > int timeout = -1; > int poll_errno; > struct tevent_fd *fde = NULL; >+ struct tevent_fd *next = NULL; > unsigned i; > > if (ev->signal_events && tevent_common_check_signal(ev)) { >@@ -542,11 +543,13 @@ static int poll_event_loop_poll(struct tevent_context *ev, > which ones and call the handler, being careful to allow > the handler to remove itself when called */ > >- for (fde = ev->fd_events; fde; fde = fde->next) { >+ for (fde = ev->fd_events; fde; fde = next) { > uint64_t idx = fde->additional_flags; > struct pollfd *pfd; > uint16_t flags = 0; > >+ next = fde->next; >+ > if (idx == UINT64_MAX) { > continue; > } >-- >2.5.0 > > >From c07c40ec2176287378871ee28b81927953d55cff Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Tue, 17 Nov 2015 09:13:41 -0800 >Subject: [PATCH 07/14] lib: tevent: Whitespace cleanup. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> > >Autobuild-User(master): Volker Lendecke <vl@samba.org> >Autobuild-Date(master): Wed Nov 18 15:54:03 CET 2015 on sn-devel-104 > >(cherry picked from commit 39d0a81ed87c58836335ec10af22b36c9961f91e) >--- > lib/tevent/tevent_epoll.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > >diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c >index 01fcde6..507ea5c 100644 >--- a/lib/tevent/tevent_epoll.c >+++ b/lib/tevent/tevent_epoll.c >@@ -216,7 +216,7 @@ static void epoll_update_event(struct epoll_event_context *epoll_ev, struct teve > > /* > reopen the epoll handle when our pid changes >- see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an >+ see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an > demonstration of why this is needed > */ > static void epoll_check_reopen(struct epoll_event_context *epoll_ev) >@@ -661,7 +661,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval > } > > for (i=0;i<ret;i++) { >- struct tevent_fd *fde = talloc_get_type(events[i].data.ptr, >+ struct tevent_fd *fde = talloc_get_type(events[i].data.ptr, > struct tevent_fd); > uint16_t flags = 0; > struct tevent_fd *mpx_fde = NULL; >@@ -888,7 +888,7 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) > } > > /* >- do a single event loop using the events defined in ev >+ do a single event loop using the events defined in ev > */ > static int epoll_event_loop_once(struct tevent_context *ev, const char *location) > { >-- >2.5.0 > > >From b72bafedf9c3d07315648844e6e93f1406bcaea2 Mon Sep 17 00:00:00 2001 >From: Jelmer Vernooij <jelmer@jelmer.uk> >Date: Wed, 18 Nov 2015 02:59:37 +0000 >Subject: [PATCH 08/14] Set LD_LIBRARY_PATH during tests. > >Without this, tests fail ir libtevent is not installed on the system. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-Off-By: Jelmer Vernooij <jelmer@jelmer.uk> >Reviewed-by: Jeremy Allison <jra@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Wed Nov 18 21:40:26 CET 2015 on sn-devel-104 > >(cherry picked from commit bf06a5166ed29e82c4efdb86cf2634f424c29931) >--- > lib/tevent/wscript | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/lib/tevent/wscript b/lib/tevent/wscript >index 4c5fe0c..73871d8 100755 >--- a/lib/tevent/wscript >+++ b/lib/tevent/wscript >@@ -133,6 +133,9 @@ def test(ctx): > '''test tevent''' > print("The tevent testsuite is part of smbtorture in samba4") > >+ samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') >+ samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') >+ > pyret = samba_utils.RUN_PYTHON_TESTS(['bindings.py']) > sys.exit(pyret) > >-- >2.5.0 > > >From 9fa7544f3e43225c16736832b27916bd59a5e3e6 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= <jelmer@jelmer.uk> >Date: Sat, 9 Jan 2016 20:25:17 +0000 >Subject: [PATCH 09/14] Simplify handling of dependencies on external libraries > in test_headers. >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >Signed-off-by: Jelmer Vernooij <jelmer@jelmer.uk> >(cherry picked from commit 3123e2c66a29aaabad7408107bcf4a0e841a93ec) >--- > testsuite/headers/wscript_build | 13 ++----------- > 1 file changed, 2 insertions(+), 11 deletions(-) > >diff --git a/testsuite/headers/wscript_build b/testsuite/headers/wscript_build >index d0625a0..64b10ba 100644 >--- a/testsuite/headers/wscript_build >+++ b/testsuite/headers/wscript_build >@@ -24,22 +24,13 @@ bld.SAMBA_GENERATOR('test_headers.h', > source=public_headers, > target='test_headers.h') > >-cflags='' >-for lib in ['talloc', 'tevent', 'tdb', 'ldb', 'popt' ]: >- ename = 'CPPPATH_%s' % lib.upper() >- for p in bld.env[ename]: >- cflags += bld.env.CPPPATH_ST % p + ' ' >- >-if not bld.env.USING_SYSTEM_POPT: >- cflags += bld.env.CPPPATH_ST % '../third_party/popt' >- > if bld.env.DEVELOPER_MODE: > bld.SAMBA_BINARY('test_headers', > source='test_headers.c', > includes="#include/public", > pyembed=True, >- cflags=cflags, > local_include=True, > global_include=False, > use_global_deps=False, >- install=False) >+ install=False, >+ deps='talloc tdb ldb tevent popt') >-- >2.5.0 > > >From eeeb94c34e0d834c16937ee338484e6a9f9beb0d Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= <jelmer@jelmer.uk> >Date: Mon, 4 Jan 2016 23:01:26 +0000 >Subject: [PATCH 10/14] tevent: Only set public headers field when installing > as a public library. >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jelmer Vernooij <jelmer@jelmer.uk> >(cherry picked from commit 2cba4918dbe82fb9d0455c73d35aa551dccc924f) >--- > lib/tevent/wscript | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/lib/tevent/wscript b/lib/tevent/wscript >index 73871d8..103cc06 100755 >--- a/lib/tevent/wscript >+++ b/lib/tevent/wscript >@@ -107,7 +107,7 @@ def build(bld): > abi_directory='ABI', > abi_match='tevent_* _tevent_*', > vnum=VERSION, >- public_headers='tevent.h', >+ public_headers=('' if private_library else 'tevent.h'), > public_headers_install=not private_library, > pc_files='tevent.pc', > private_library=private_library) >-- >2.5.0 > > >From fc08c0e3f628f9d4634bd987922b9690aa51a3e3 Mon Sep 17 00:00:00 2001 >From: Nathan Huff <nhuff@acm.org> >Date: Fri, 5 Feb 2016 13:35:07 -0700 >Subject: [PATCH 11/14] Fix ETIME handling for Solaris event ports. >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >It is possible for port_getn to return -1 with errno set to ETIME and >still return events. If those events aren't processed the association is >lost by samba since the kernel dissacociated them and samba never >processed them so never reassociated them with the event port. The >patch checks the nget return value in the case of ETIME and if it is non >0 it doesn't return and goes through the event processing loop. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Nathan Huff <nhuff@acm.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> > >Autobuild-User(master): Ralph Böhme <slow@samba.org> >Autobuild-Date(master): Sun Feb 7 11:26:35 CET 2016 on sn-devel-144 > >(cherry picked from commit 4953b1f73f8ec9387516be1058434d71937e1447) >--- > lib/tevent/tevent_port.c | 22 ++++++++++++++++++---- > 1 file changed, 18 insertions(+), 4 deletions(-) > >diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c >index 5b487d7..4b524df 100644 >--- a/lib/tevent/tevent_port.c >+++ b/lib/tevent/tevent_port.c >@@ -496,10 +496,24 @@ static int port_event_loop(struct port_event_context *port_ev, struct timeval *t > return 0; > } > >- if (ret == -1 && port_errno == ETIME && tvalp) { >- /* we don't care about a possible delay here */ >- tevent_common_loop_timer_delay(ev); >- return 0; >+ if (ret == -1 && port_errno == ETIME) { >+ /* >+ * If errno is set to ETIME it is possible that we still got an event. >+ * In that case we need to go through the processing loop so that we >+ * reassociate the received event with the port or the association will >+ * be lost so check the value of nget is 0 before returning. >+ */ >+ if (nget == 0) { >+ /* we don't care about a possible delay here */ >+ tevent_common_loop_timer_delay(ev); >+ return 0; >+ } >+ /* >+ * Set the return value to 0 since we do not actually have an error and we >+ * do have events that need to be processed. This keeps us from getting >+ * caught in the generic error test. >+ */ >+ ret = 0; > } > > if (ret == -1) { >-- >2.5.0 > > >From 455b56ad5d92617f99ed25803072b2fbfb8d1a52 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 15 Feb 2016 11:40:34 +0100 >Subject: [PATCH 12/14] tevent: version 0.9.27 > >* Fix bug in poll backend - poll_event_loop_poll() > exits the for loop on POLLNVAL instead of > continuing to find an event that is ready. >* Fix ETIME handling for Solaris event ports (bug #11728). > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Michael Adam <obnox@samba.org> > >Autobuild-User(master): Michael Adam <obnox@samba.org> >Autobuild-Date(master): Tue Feb 16 00:00:51 CET 2016 on sn-devel-144 > >(cherry picked from commit 2267faddfa9863b205dfad580fbd45182916cb32) >--- > lib/tevent/ABI/tevent-0.9.27.sigs | 90 +++++++++++++++++++++++++++++++++++++++ > lib/tevent/wscript | 2 +- > 2 files changed, 91 insertions(+), 1 deletion(-) > create mode 100644 lib/tevent/ABI/tevent-0.9.27.sigs > >diff --git a/lib/tevent/ABI/tevent-0.9.27.sigs b/lib/tevent/ABI/tevent-0.9.27.sigs >new file mode 100644 >index 0000000..1357751 >--- /dev/null >+++ b/lib/tevent/ABI/tevent-0.9.27.sigs >@@ -0,0 +1,90 @@ >+_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_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_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_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_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_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_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 103cc06..501de16 100755 >--- a/lib/tevent/wscript >+++ b/lib/tevent/wscript >@@ -1,7 +1,7 @@ > #!/usr/bin/env python > > APPNAME = 'tevent' >-VERSION = '0.9.26' >+VERSION = '0.9.27' > > blddir = 'bin' > >-- >2.5.0 > > >From e8f10e942dace966df7b88cc1a11ae8c97d51d58 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Tue, 16 Feb 2016 14:23:53 -0800 >Subject: [PATCH 13/14] =?UTF-8?q?lib:=20tevent:=20Fix=20memory=20leak=20re?= > =?UTF-8?q?ported=20by=20Pavel=20B=C5=99ezina=20<pbrezina@redhat.com>=20wh?= > =?UTF-8?q?en=20old=20signal=20action=20restored.?= >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=11742 >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> > >Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org> >Autobuild-Date(master): Thu Feb 18 01:42:50 CET 2016 on sn-devel-144 > >(cherry picked from commit 833a2f474367624dd9980abb28227850e95fe976) >--- > lib/tevent/tevent_signal.c | 4 ++++ > 1 file changed, 4 insertions(+) > >diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c >index 924dc05..9bc11ed 100644 >--- a/lib/tevent/tevent_signal.c >+++ b/lib/tevent/tevent_signal.c >@@ -212,6 +212,7 @@ static int tevent_signal_destructor(struct tevent_signal *se) > /* restore old handler, if any */ > if (sig_state->oldact[se->signum]) { > sigaction(se->signum, sig_state->oldact[se->signum], NULL); >+ talloc_free(sig_state->oldact[se->signum]); > sig_state->oldact[se->signum] = NULL; > } > #ifdef SA_SIGINFO >@@ -342,6 +343,8 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev, > return NULL; > } > if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) { >+ talloc_free(sig_state->oldact[signum]); >+ sig_state->oldact[signum] = NULL; > talloc_free(se); > return NULL; > } >@@ -505,6 +508,7 @@ void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se) > if (sig_state->sig_handlers[se->signum] == NULL) { > if (sig_state->oldact[se->signum]) { > sigaction(se->signum, sig_state->oldact[se->signum], NULL); >+ talloc_free(sig_state->oldact[se->signum]); > sig_state->oldact[se->signum] = NULL; > } > } >-- >2.5.0 > > >From bf2a47dd4397057df55d732f1ecd8a02c7f54fd7 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 Feb 2016 11:46:03 +0100 >Subject: [PATCH 14/14] tevent: version 0.9.28 > >* Fix memory leak when old signal action restored (bug #11742) > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11771 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Fri Feb 19 19:12:25 CET 2016 on sn-devel-144 > >(cherry picked from commit da74d0c317be9ce67eb5d00d232167d466f68a1e) > >The last 13 patches addressed bug #11771: >Backport tevent 0.9.28. >--- > lib/tevent/ABI/tevent-0.9.28.sigs | 90 +++++++++++++++++++++++++++++++++++++++ > lib/tevent/wscript | 2 +- > 2 files changed, 91 insertions(+), 1 deletion(-) > create mode 100644 lib/tevent/ABI/tevent-0.9.28.sigs > >diff --git a/lib/tevent/ABI/tevent-0.9.28.sigs b/lib/tevent/ABI/tevent-0.9.28.sigs >new file mode 100644 >index 0000000..1357751 >--- /dev/null >+++ b/lib/tevent/ABI/tevent-0.9.28.sigs >@@ -0,0 +1,90 @@ >+_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_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_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_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_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_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_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 501de16..2bdb5ac 100755 >--- a/lib/tevent/wscript >+++ b/lib/tevent/wscript >@@ -1,7 +1,7 @@ > #!/usr/bin/env python > > APPNAME = 'tevent' >-VERSION = '0.9.27' >+VERSION = '0.9.28' > > blddir = 'bin' > >-- >2.5.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review+
jra
:
review+
Actions:
View
Attachments on
bug 11771
:
11893
|
11895
|
11896
|
11918
| 11919