summaryrefslogtreecommitdiff
path: root/event.c
diff options
context:
space:
mode:
authorJosé Luis Millán <jmillan@aliax.net>2015-04-13 08:54:52 +0200
committerAzat Khuzhin <a3at.mail@gmail.com>2017-04-30 01:40:42 +0300
commit0b4b0efdb8ee710ccae5bad320fc24843fd428e5 (patch)
tree623a9ecab45c1a723a958d99b6d64d9b9a726bf5 /event.c
parent5ff83989f30daef93a851c2162667375ed1663a5 (diff)
downloadlibevent-0b4b0efdb8ee710ccae5bad320fc24843fd428e5.tar.gz
Return from event_del() after the last event callback termination
Delete the event from the queue before blocking for the current event callback termination. Ensures that no callback is being executed when event_del() returns, hence making this function a secure mechanism to access data which is handled in the event callack. Fixes: #236 Fixes: #225 Refs: 6b4b77a Fixes: del_wait
Diffstat (limited to 'event.c')
-rw-r--r--event.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/event.c b/event.c
index 918b412d..d2768793 100644
--- a/event.c
+++ b/event.c
@@ -2780,21 +2780,7 @@ event_del_nolock_(struct event *ev, int blocking)
}
}
- /* If the main thread is currently executing this event's callback,
- * and we are not the main thread, then we want to wait until the
- * callback is done before we start removing the event. That way,
- * when this function returns, it will be safe to free the
- * user-supplied argument. */
base = ev->ev_base;
-#ifndef EVENT__DISABLE_THREAD_SUPPORT
- if (blocking != EVENT_DEL_NOBLOCK &&
- base->current_event == event_to_event_callback(ev) &&
- !EVBASE_IN_THREAD(base) &&
- (blocking == EVENT_DEL_BLOCK || !(ev->ev_events & EV_FINALIZE))) {
- ++base->current_event_waiters;
- EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
- }
-#endif
EVUTIL_ASSERT(!(ev->ev_flags & ~EVLIST_ALL));
@@ -2841,6 +2827,21 @@ event_del_nolock_(struct event *ev, int blocking)
event_debug_note_del_(ev);
+ /* If the main thread is currently executing this event's callback,
+ * and we are not the main thread, then we want to wait until the
+ * callback is done before returning. That way, when this function
+ * returns, it will be safe to free the user-supplied argument.
+ */
+#ifndef EVENT__DISABLE_THREAD_SUPPORT
+ if (blocking != EVENT_DEL_NOBLOCK &&
+ base->current_event == event_to_event_callback(ev) &&
+ !EVBASE_IN_THREAD(base) &&
+ (blocking == EVENT_DEL_BLOCK || !(ev->ev_events & EV_FINALIZE))) {
+ ++base->current_event_waiters;
+ EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
+ }
+#endif
+
return (res);
}