[PATCHES] some new tevent features

Volker Lendecke Volker.Lendecke at SerNet.DE
Fri Jan 17 04:20:42 MST 2014


On Fri, Jan 17, 2014 at 11:50:44AM +0100, Volker Lendecke wrote:
> On Mon, Jan 13, 2014 at 09:11:42PM +0100, Stefan (metze) Metzmacher wrote:
> > Hi Volker,
> > 
> > >>>> static int smbXcli_req_destructor(struct tevent_req *req)
> > >>>> static int fncall_destructor(struct tevent_req *req)
> > >>>> static int tldap_msg_destructor(struct tevent_req *req)
> > >>>
> > >>> Thanks for checking. Maybe I was a bit worried because 2 of
> > >>> those are mine ... :-)
> > >>
> > >> Can you review the attached patches?
> > > 
> > > Please don't push this patches yet, I'm currently debugging a possible
> > > problem...
> > 
> > There was a bug in the interaction with tevent_req_defer_callback()
> > and tevent_req_set_cleanup_fn().
> > 
> > This bug is fixed in the attached patchset (it's also a bit cleaner this
> > way).
> > We rely the tevent_req_state enum being sorted, we only trigger
> > the cleanup function once per state and remember the last state
> > and skip the cleanup function on the 2nd call.
> 
> Pushed to master with a little re-wording in doxygen:

Ok, stopped the autobuild and created a new patchset with
your requested changes.

Feel free to push.

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 3f2a682a28f674eb4e660c6a1a5cc7ec35959848 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 11 Jan 2014 08:58:05 +0100
Subject: [PATCH 01/11] tevent: fix crash bug in
 tevent_queue_immediate_trigger()

Assume we we have a queue with 2 entries (A and B with triggerA() and triggerB()).
If triggerA() removes itself tevent_queue_entry_destructor() will be called
for A, this schedules the immediate event to call triggerB().
If triggerA() then also removes B by an explicit of implizit talloc_free(),
q->list is NULL, but the immediate event is still scheduled and can't be unscheduled.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 lib/tevent/tevent_queue.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
index 930319c..35742e5 100644
--- a/lib/tevent/tevent_queue.c
+++ b/lib/tevent/tevent_queue.c
@@ -141,6 +141,10 @@ static void tevent_queue_immediate_trigger(struct tevent_context *ev,
 		return;
 	}
 
+	if (!q->list) {
+		return;
+	}
+
 	q->list->triggered = true;
 	q->list->trigger(q->list->req, q->list->private_data);
 }
-- 
1.7.9.5


From bfb822b1504538d7d623665238c5bb0809ae758e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 13 Dec 2013 11:59:43 +0100
Subject: [PATCH 02/11] tevent: Only build "std_fallback_to_poll" when epoll
 is around

Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/tevent/tevent_standard.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c
index 785d68d..a050901 100644
--- a/lib/tevent/tevent_standard.c
+++ b/lib/tevent/tevent_standard.c
@@ -54,6 +54,7 @@ static const struct tevent_ops std_event_ops = {
   Move us to using poll instead. If we return false here,
   caller should abort().
 */
+#ifdef HAVE_EPOLL
 static bool std_fallback_to_poll(struct tevent_context *ev, bool replay)
 {
 	void *glue_ptr = talloc_parent(ev->ops);
@@ -100,6 +101,7 @@ static bool std_fallback_to_poll(struct tevent_context *ev, bool replay)
 
 	return true;
 }
+#endif
 
 static int std_event_loop_once(struct tevent_context *ev, const char *location)
 {
-- 
1.7.9.5


From a74531a190f7f7e7dac249773076232f34acf0f3 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 13 Dec 2013 11:59:04 +0100
Subject: [PATCH 03/11] tevent: Add prototypes

... doxygen docs to be filled in :-)

Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/tevent/tevent.h |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 0705ff3..3f8e081 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -340,6 +340,10 @@ struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
 			   #handler, __location__)
 #endif
 
+size_t tevent_num_signals(void);
+
+size_t tevent_sa_info_queue_count(void);
+
 #ifdef DOXYGEN
 /**
  * @brief Pass a single time through the mainloop
-- 
1.7.9.5


From 1c837003cad3eafcea1fb34f67db2de673d7f9bf Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 8 Jan 2014 10:01:56 +0100
Subject: [PATCH 04/11] tevent: add doxygen comments for tevent_num_signals()
 and tevent_sa_info_queue_count()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 lib/tevent/tevent.h |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 3f8e081..d7d4f19 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -319,6 +319,8 @@ void _tevent_schedule_immediate(struct tevent_immediate *im,
  *
  * @note To cancel a signal handler, call talloc_free() on the event returned
  * from this function.
+ *
+ * @see tevent_num_signals, tevent_sa_info_queue_count
  */
 struct tevent_signal *tevent_add_signal(struct tevent_context *ev,
                      TALLOC_CTX *mem_ctx,
@@ -340,8 +342,29 @@ struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
 			   #handler, __location__)
 #endif
 
+/**
+ * @brief the number of supported signals
+ *
+ * This returns value of the configure time TEVENT_NUM_SIGNALS constant.
+ *
+ * The 'signum' argument of tevent_add_signal() must be less than
+ * TEVENT_NUM_SIGNALS.
+ *
+ * @see tevent_add_signal
+ */
 size_t tevent_num_signals(void);
 
+/**
+ * @brief the number of pending realtime signals
+ *
+ * This returns value of TEVENT_SA_INFO_QUEUE_COUNT.
+ *
+ * The tevent internals remember the last TEVENT_SA_INFO_QUEUE_COUNT
+ * siginfo_t structures for SA_SIGINFO signals. If the system generates
+ * more some signals get lost.
+ *
+ * @see tevent_add_signal
+ */
 size_t tevent_sa_info_queue_count(void);
 
 #ifdef DOXYGEN
-- 
1.7.9.5


From 573e534d25676f40d726f0ae0c4357267fa76529 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 27 Sep 2013 03:41:29 +0200
Subject: [PATCH 05/11] tevent: add/use tevent_req_destructor

This makes sure we call tevent_req_received(req) on talloc_free()
and cleanup things in a defined order.

Note that some callers used their own destructor for their
tevent_req instance, they'll just overwrite this,
which is not intended, but works without problems.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 lib/tevent/tevent_req.c |   15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c
index edb8550..30e91e2 100644
--- a/lib/tevent/tevent_req.c
+++ b/lib/tevent/tevent_req.c
@@ -51,6 +51,8 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
 	return req->private_print(req, mem_ctx);
 }
 
+static int tevent_req_destructor(struct tevent_req *req);
+
 struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
 				    void *pdata,
 				    size_t data_size,
@@ -86,10 +88,18 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
 
 	req->data = data;
 
+	talloc_set_destructor(req, tevent_req_destructor);
+
 	*ppdata = data;
 	return req;
 }
 
+static int tevent_req_destructor(struct tevent_req *req)
+{
+	tevent_req_received(req);
+	return 0;
+}
+
 void _tevent_req_notify_callback(struct tevent_req *req, const char *location)
 {
 	req->internal.finish_location = location;
@@ -200,7 +210,8 @@ bool tevent_req_is_in_progress(struct tevent_req *req)
 
 void tevent_req_received(struct tevent_req *req)
 {
-	TALLOC_FREE(req->data);
+	talloc_set_destructor(req, NULL);
+
 	req->private_print = NULL;
 	req->private_cancel = NULL;
 
@@ -208,6 +219,8 @@ void tevent_req_received(struct tevent_req *req)
 	TALLOC_FREE(req->internal.timer);
 
 	req->internal.state = TEVENT_REQ_RECEIVED;
+
+	TALLOC_FREE(req->data);
 }
 
 bool tevent_req_poll(struct tevent_req *req,
-- 
1.7.9.5


From 01d95caacfa6b010fd0a2a8740fb8c238e0e3478 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 27 Sep 2013 02:29:57 +0200
Subject: [PATCH 06/11] tevent: add tevent_req_set_cleanup_fn()

Note that some callers used their own destructor for their
tevent_req instance, they'll just overwrite this,
which is not intended, but works without problems.

The intended way is to specify a cleanup function
and handle the TEVENT_REQ_RECEIVED state as destructor.

Note that the TEVENT_REQ_RECEIVED cleanup event might
be triggered by an explicit tevent_req_received()
in the _recv() function. The TEVENT_REQ_RECEIVED event
is only triggered once as tevent_req_received()
will remove the destructor.

So the difference compared to a custom destructor
is that the struct tevent_req itself can continue
to be there, while tevent_req_received() removed
all internal state.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 lib/tevent/tevent.h          |   35 +++++++++++++++++++++++++++++++++++
 lib/tevent/tevent_internal.h |   12 ++++++++++++
 lib/tevent/tevent_req.c      |   30 ++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index d7d4f19..c54cbe2 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -934,6 +934,41 @@ bool _tevent_req_cancel(struct tevent_req *req, const char *location);
 	_tevent_req_cancel(req, __location__)
 #endif
 
+/**
+ * @brief A typedef for a cleanup function for a tevent request.
+ *
+ * @param[in]  req       The tevent request calling this function.
+ *
+ * @param[in]  req_state The current tevent_req_state.
+ *
+ */
+typedef void (*tevent_req_cleanup_fn)(struct tevent_req *req,
+				      enum tevent_req_state req_state);
+
+/**
+ * @brief This function sets a cleanup function for the given tevent request.
+ *
+ * This function can be used to setup a cleanup function for the given request.
+ * This will be triggered when the tevent_req_done() or tevent_req_error()
+ * function was called, before notifying the callers callback function,
+ * and also before scheduling the deferred trigger.
+ *
+ * This might be useful if more than one tevent_req belong together
+ * and need to finish both requests at the same time.
+ *
+ * The cleanup function is able to call tevent_req_done() or tevent_req_error()
+ * recursively, the cleanup function is only triggered the first time.
+ *
+ * The cleanup function is also called by tevent_req_received()
+ * (possibly triggered from tevent_req_destructor()) before destroying
+ * the private data of the tevent_req.
+ *
+ * @param[in]  req      The request to use.
+ *
+ * @param[in]  fn       A pointer to the cancel function.
+ */
+void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn);
+
 #ifdef DOXYGEN
 /**
  * @brief Create an async tevent request.
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index df73288..d25dc05 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -74,6 +74,18 @@ struct tevent_req {
 	tevent_req_cancel_fn private_cancel;
 
 	/**
+	 * @brief A function to cleanup the request
+	 *
+	 * The implementation might want to set a function
+	 * that is called before the tevent_req_done() and tevent_req_error()
+	 * trigger the callers callback function.
+	 */
+	struct {
+		tevent_req_cleanup_fn fn;
+		enum tevent_req_state state;
+	} private_cleanup;
+
+	/**
 	 * @brief Internal state of the request
 	 *
 	 * Callers should only access this via functions and never directly.
diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c
index 30e91e2..c86fb68 100644
--- a/lib/tevent/tevent_req.c
+++ b/lib/tevent/tevent_req.c
@@ -113,6 +113,24 @@ void _tevent_req_notify_callback(struct tevent_req *req, const char *location)
 	}
 }
 
+static void tevent_req_cleanup(struct tevent_req *req)
+{
+	if (req->private_cleanup.fn == NULL) {
+		return;
+	}
+
+	if (req->private_cleanup.state >= req->internal.state) {
+		/*
+		 * Don't call the cleanup_function multiple times for the same
+		 * state recursively
+		 */
+		return;
+	}
+
+	req->private_cleanup.state = req->internal.state;
+	req->private_cleanup.fn(req, req->internal.state);
+}
+
 static void tevent_req_finish(struct tevent_req *req,
 			      enum tevent_req_state state,
 			      const char *location)
@@ -124,6 +142,10 @@ static void tevent_req_finish(struct tevent_req *req,
 	TALLOC_FREE(req->internal.timer);
 
 	req->internal.state = state;
+	req->internal.finish_location = location;
+
+	tevent_req_cleanup(req);
+
 	_tevent_req_notify_callback(req, location);
 }
 
@@ -220,6 +242,8 @@ void tevent_req_received(struct tevent_req *req)
 
 	req->internal.state = TEVENT_REQ_RECEIVED;
 
+	tevent_req_cleanup(req);
+
 	TALLOC_FREE(req->data);
 }
 
@@ -315,3 +339,9 @@ bool _tevent_req_cancel(struct tevent_req *req, const char *location)
 
 	return req->private_cancel(req);
 }
+
+void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn)
+{
+	req->private_cleanup.state = req->internal.state;
+	req->private_cleanup.fn = fn;
+}
-- 
1.7.9.5


From ad8b682354ae5dfd8a139173f3012cfb1a217480 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 27 Sep 2013 04:06:00 +0200
Subject: [PATCH 07/11] tevent: version 0.9.21

This fixes a the following bugs:
- fix a crash bug in tevent_queue_immediate_trigger()
- add missing tevent_num_signals() and
  tevent_sa_info_queue_count() prototypes
  including documentation.

This adds the following new features:

- tevent_req_set_cleanup_fn()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 lib/tevent/ABI/tevent-0.9.21.sigs |   88 +++++++++++++++++++++++++++++++++++++
 lib/tevent/wscript                |    2 +-
 2 files changed, 89 insertions(+), 1 deletion(-)
 create mode 100644 lib/tevent/ABI/tevent-0.9.21.sigs

diff --git a/lib/tevent/ABI/tevent-0.9.21.sigs b/lib/tevent/ABI/tevent-0.9.21.sigs
new file mode 100644
index 0000000..d8b9f4b
--- /dev/null
+++ b/lib/tevent/ABI/tevent-0.9.21.sigs
@@ -0,0 +1,88 @@
+_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_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 3fc87f5..bd19780 100755
--- a/lib/tevent/wscript
+++ b/lib/tevent/wscript
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 APPNAME = 'tevent'
-VERSION = '0.9.20'
+VERSION = '0.9.21'
 
 blddir = 'bin'
 
-- 
1.7.9.5


From a451ef9533485556899bff94642a8fb78ee954e3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 8 Jan 2014 10:31:15 +0100
Subject: [PATCH 08/11] libcli/smb: make use of tevent_req_set_cleanup_fn()

This is more better than a custom tevent_req destructor.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 libcli/smb/smbXcli_base.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 082b626..43dd994 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -785,7 +785,7 @@ void smbXcli_req_unset_pending(struct tevent_req *req)
 		return;
 	}
 
-	talloc_set_destructor(req, NULL);
+	tevent_req_set_cleanup_fn(req, NULL);
 
 	if (num_pending == 1) {
 		/*
@@ -828,19 +828,25 @@ void smbXcli_req_unset_pending(struct tevent_req *req)
 	return;
 }
 
-static int smbXcli_req_destructor(struct tevent_req *req)
+static void smbXcli_req_cleanup(struct tevent_req *req,
+				enum tevent_req_state req_state)
 {
 	struct smbXcli_req_state *state =
 		tevent_req_data(req,
 		struct smbXcli_req_state);
 
-	/*
-	 * Make sure we really remove it from
-	 * the pending array on destruction.
-	 */
-	state->smb1.mid = 0;
-	smbXcli_req_unset_pending(req);
-	return 0;
+	switch (req_state) {
+	case TEVENT_REQ_RECEIVED:
+		/*
+		 * Make sure we really remove it from
+		 * the pending array on destruction.
+		 */
+		state->smb1.mid = 0;
+		smbXcli_req_unset_pending(req);
+		return;
+	default:
+		return;
+	}
 }
 
 static bool smb1cli_req_cancel(struct tevent_req *req);
@@ -893,7 +899,7 @@ bool smbXcli_req_set_pending(struct tevent_req *req)
 	}
 	pending[num_pending] = req;
 	conn->pending = pending;
-	talloc_set_destructor(req, smbXcli_req_destructor);
+	tevent_req_set_cleanup_fn(req, smbXcli_req_cleanup);
 	tevent_req_set_cancel_fn(req, smbXcli_req_cancel);
 
 	if (!smbXcli_conn_receive_next(conn)) {
-- 
1.7.9.5


From 26a52c44b5e74fa7f456d9fbf0249da8c47b9369 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 8 Jan 2014 10:31:15 +0100
Subject: [PATCH 09/11] s3:lib/fncall: make use of tevent_req_set_cleanup_fn()

This is more better than a custom tevent_req destructor.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/fncall.c |   23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/source3/lib/fncall.c b/source3/lib/fncall.c
index fb3d5c9..7f728ba 100644
--- a/source3/lib/fncall.c
+++ b/source3/lib/fncall.c
@@ -122,7 +122,8 @@ static int fncall_next_job_id(struct fncall_context *ctx)
 }
 
 static void fncall_unset_pending(struct tevent_req *req);
-static int fncall_destructor(struct tevent_req *req);
+static void fncall_cleanup(struct tevent_req *req,
+			   enum tevent_req_state req_state);
 
 static bool fncall_set_pending(struct tevent_req *req,
 			       struct fncall_context *ctx,
@@ -141,12 +142,12 @@ static bool fncall_set_pending(struct tevent_req *req,
 	pending[num_pending] = req;
 	num_pending += 1;
 	ctx->pending = pending;
-	talloc_set_destructor(req, fncall_destructor);
+	tevent_req_set_cleanup_fn(req, fncall_cleanup);
 
 	/*
 	 * Make sure that the orphaned array of fncall_state structs has
 	 * enough space. A job can change from pending to orphaned in
-	 * fncall_destructor, and to fail in a talloc destructor should be
+	 * fncall_cleanup, and to fail in a talloc destructor should be
 	 * avoided if possible.
 	 */
 
@@ -184,6 +185,8 @@ static void fncall_unset_pending(struct tevent_req *req)
 	int num_pending = talloc_array_length(ctx->pending);
 	int i;
 
+	tevent_req_set_cleanup_fn(req, NULL);
+
 	if (num_pending == 1) {
 		TALLOC_FREE(ctx->fde);
 		TALLOC_FREE(ctx->pending);
@@ -205,16 +208,24 @@ static void fncall_unset_pending(struct tevent_req *req)
 				      num_pending - 1);
 }
 
-static int fncall_destructor(struct tevent_req *req)
+static void fncall_cleanup(struct tevent_req *req,
+			   enum tevent_req_state req_state)
 {
 	struct fncall_state *state = tevent_req_data(
 		req, struct fncall_state);
 	struct fncall_context *ctx = state->ctx;
 
+	switch (req_state) {
+	case TEVENT_REQ_RECEIVED:
+		break;
+	default:
+		return;
+	}
+
 	fncall_unset_pending(req);
 
 	if (state->done) {
-		return 0;
+		return;
 	}
 
 	/*
@@ -223,8 +234,6 @@ static int fncall_destructor(struct tevent_req *req)
 	 */
 	ctx->orphaned[ctx->num_orphaned] = talloc_move(ctx->orphaned, &state);
 	ctx->num_orphaned += 1;
-
-	return 0;
 }
 
 struct tevent_req *fncall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-- 
1.7.9.5


From fbef6107545c5b04675330ee402e625fb040595e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 8 Jan 2014 19:46:01 +0100
Subject: [PATCH 10/11] s3:lib/tldap: make use of tevent_req_defer_callback()

In tldap_msg_received() we call tevent_req_error() for more than
one request, if we do that we need to use tevent_req_defer_callback()
otherwise we're likely to crash, as a triggered callback may
invalidate our state.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/tldap.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index b094c2d..a566a91 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -650,6 +650,8 @@ static void tldap_msg_received(struct tevent_req *subreq)
  fail:
 	while (talloc_array_length(ld->pending) > 0) {
 		req = ld->pending[0];
+		state = tevent_req_data(req, struct tldap_msg_state);
+		tevent_req_defer_callback(req, state->ev);
 		talloc_set_destructor(req, NULL);
 		tldap_msg_destructor(req);
 		tevent_req_error(req, status);
-- 
1.7.9.5


From 53cd5d22eb0c2cae8e8f4e023b35026ec98fc910 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 8 Jan 2014 10:31:15 +0100
Subject: [PATCH 11/11] s3:lib/tldap: make use of tevent_req_set_cleanup_fn()

This is more better than a custom tevent_req destructor.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/tldap.c |   20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index a566a91..b15ee73 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -444,6 +444,8 @@ static void tldap_msg_unset_pending(struct tevent_req *req)
 	int num_pending = talloc_array_length(ld->pending);
 	int i;
 
+	tevent_req_set_cleanup_fn(req, NULL);
+
 	if (num_pending == 1) {
 		TALLOC_FREE(ld->pending);
 		return;
@@ -479,10 +481,17 @@ static void tldap_msg_unset_pending(struct tevent_req *req)
 	return;
 }
 
-static int tldap_msg_destructor(struct tevent_req *req)
+static void tldap_msg_cleanup(struct tevent_req *req,
+			      enum tevent_req_state req_state)
 {
-	tldap_msg_unset_pending(req);
-	return 0;
+	switch (req_state) {
+	case TEVENT_REQ_USER_ERROR:
+	case TEVENT_REQ_RECEIVED:
+		tldap_msg_unset_pending(req);
+		return;
+	default:
+		return;
+	}
 }
 
 static bool tldap_msg_set_pending(struct tevent_req *req)
@@ -504,7 +513,7 @@ static bool tldap_msg_set_pending(struct tevent_req *req)
 	}
 	pending[num_pending] = req;
 	ld->pending = pending;
-	talloc_set_destructor(req, tldap_msg_destructor);
+	tevent_req_set_cleanup_fn(req, tldap_msg_cleanup);
 
 	if (num_pending > 0) {
 		return true;
@@ -618,7 +627,6 @@ static void tldap_msg_received(struct tevent_req *subreq)
 	state->inbuf = talloc_move(state, &inbuf);
 	state->data = talloc_move(state, &data);
 
-	talloc_set_destructor(req, NULL);
 	tldap_msg_unset_pending(req);
 	num_pending = talloc_array_length(ld->pending);
 
@@ -652,8 +660,6 @@ static void tldap_msg_received(struct tevent_req *subreq)
 		req = ld->pending[0];
 		state = tevent_req_data(req, struct tldap_msg_state);
 		tevent_req_defer_callback(req, state->ev);
-		talloc_set_destructor(req, NULL);
-		tldap_msg_destructor(req);
 		tevent_req_error(req, status);
 	}
 }
-- 
1.7.9.5



More information about the samba-technical mailing list