The branch, master has been updated via 741cb24 s3:lib/tldap: make use of tevent_req_set_cleanup_fn() via 5fd9eab s3:lib/tldap: make use of tevent_req_defer_callback() via c84fe17 s3:lib/fncall: make use of tevent_req_set_cleanup_fn() via f08c0b2 libcli/smb: make use of tevent_req_set_cleanup_fn() via c4c88d1 tevent: version 0.9.21 via 50b9f15 tevent: add tevent_req_set_cleanup_fn() via 0ed93e0 tevent: add/use tevent_req_destructor via 7502a30 tevent: add doxygen comments for tevent_num_signals() and tevent_sa_info_queue_count() via fd80e54 tevent: Add prototypes via e7d4b7d tevent: Only build "std_fallback_to_poll" when epoll is around via 7fe5584 tevent: fix crash bug in tevent_queue_immediate_trigger() from b7bfe46 ctdb/eventscripts: Move all eventscript state under $CTDB_VARDIR/state
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 741cb24f7a953498940d7b3ada6cb5538ec590fd Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jan 8 10:31:15 2014 +0100 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Fri Jan 17 14:34:06 CET 2014 on sn-devel-104 commit 5fd9eab20fc48f84c2ab389f91ae11d65361ccf5 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jan 8 19:46:01 2014 +0100 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit c84fe17ba954d2784cc1ac5f9e1f3a8302ca951d Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jan 8 10:31:15 2014 +0100 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit f08c0b2ef1bb92928ae86ba9d1c276a8e117367c Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jan 8 10:31:15 2014 +0100 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit c4c88d1ee8960ae0d8a392821cf4f218725ab660 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Sep 27 04:06:00 2013 +0200 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 50b9f154d22f5c356e66bba341e9ee0292218cfd Author: Stefan Metzmacher <me...@samba.org> Date: Fri Sep 27 02:29:57 2013 +0200 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 0ed93e099af833045d9d00b9a8faeb5b93b6ef2e Author: Stefan Metzmacher <me...@samba.org> Date: Fri Sep 27 03:41:29 2013 +0200 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit 7502a309e8b817036c1ddc38740c214ae416bf29 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jan 8 10:01:56 2014 +0100 tevent: add doxygen comments for tevent_num_signals() and tevent_sa_info_queue_count() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> commit fd80e544169db5fb86288b7b22da4e98a88f4477 Author: Volker Lendecke <v...@samba.org> Date: Fri Dec 13 11:59:04 2013 +0100 tevent: Add prototypes ... doxygen docs to be filled in :-) Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit e7d4b7deda2fac7a7dd86dad84bafcae8085ff80 Author: Volker Lendecke <v...@samba.org> Date: Fri Dec 13 11:59:43 2013 +0100 tevent: Only build "std_fallback_to_poll" when epoll is around Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 7fe5584e2a59584431cb2ddf8a4da22bfb924454 Author: Stefan Metzmacher <me...@samba.org> Date: Sat Jan 11 08:58:05 2014 +0100 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 <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> ----------------------------------------------------------------------- Summary of changes: .../ABI/{tevent-0.9.20.sigs => tevent-0.9.21.sigs} | 1 + lib/tevent/tevent.h | 62 ++++++++++++++++++++ lib/tevent/tevent_internal.h | 12 ++++ lib/tevent/tevent_queue.c | 4 + lib/tevent/tevent_req.c | 45 ++++++++++++++- lib/tevent/tevent_standard.c | 2 + lib/tevent/wscript | 2 +- libcli/smb/smbXcli_base.c | 26 +++++--- source3/lib/fncall.c | 23 +++++-- source3/lib/tldap.c | 22 +++++-- 10 files changed, 173 insertions(+), 26 deletions(-) copy lib/tevent/ABI/{tevent-0.9.20.sigs => tevent-0.9.21.sigs} (98%) Changeset truncated at 500 lines: diff --git a/lib/tevent/ABI/tevent-0.9.20.sigs b/lib/tevent/ABI/tevent-0.9.21.sigs similarity index 98% copy from lib/tevent/ABI/tevent-0.9.20.sigs copy to lib/tevent/ABI/tevent-0.9.21.sigs index 7b9c77d..d8b9f4b 100644 --- a/lib/tevent/ABI/tevent-0.9.20.sigs +++ b/lib/tevent/ABI/tevent-0.9.21.sigs @@ -65,6 +65,7 @@ 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) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 0705ff3..c54cbe2 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,6 +342,31 @@ 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 /** * @brief Pass a single time through the mainloop @@ -907,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_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); } diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index edb8550..c86fb68 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; @@ -103,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) @@ -114,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); } @@ -200,7 +232,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 +241,10 @@ void tevent_req_received(struct tevent_req *req) TALLOC_FREE(req->internal.timer); req->internal.state = TEVENT_REQ_RECEIVED; + + tevent_req_cleanup(req); + + TALLOC_FREE(req->data); } bool tevent_req_poll(struct tevent_req *req, @@ -302,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; +} 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) { 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' 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)) { 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, diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c index b094c2d..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); @@ -650,8 +658,8 @@ static void tldap_msg_received(struct tevent_req *subreq) fail: while (talloc_array_length(ld->pending) > 0) { req = ld->pending[0]; - talloc_set_destructor(req, NULL); - tldap_msg_destructor(req); + state = tevent_req_data(req, struct tldap_msg_state); + tevent_req_defer_callback(req, state->ev); tevent_req_error(req, status); } } -- Samba Shared Repository