diff options
author | José Luis Millán <jmillan@aliax.net> | 2015-04-13 08:54:52 +0200 |
---|---|---|
committer | Azat Khuzhin <a3at.mail@gmail.com> | 2017-04-30 01:40:42 +0300 |
commit | 0b4b0efdb8ee710ccae5bad320fc24843fd428e5 (patch) | |
tree | 623a9ecab45c1a723a958d99b6d64d9b9a726bf5 /event.c | |
parent | 5ff83989f30daef93a851c2162667375ed1663a5 (diff) | |
download | libevent-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.c | 29 |
1 files changed, 15 insertions, 14 deletions
@@ -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); } |