mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-12 13:58:58 -04:00
Fix base unlocking in event_del() if event_base_set() runned in another thread
Image next situation: T1: T2: event_del_() lock the event.ev_base.th_base_lock event_del_nolock_() event_set_base() unlock the event.ev_base.th_base_lock In this case we will unlock the wrong base after event_del_nolock_() returns, and deadlock is likely to happens, since event_base_set() do not check any mutexes (due to it is possible to do this only if event is not inserted anywhere). So event_del_() has to cache the base before removing the event, and cached base.th_base_lock after. (cherry picked from commit 08a0d366073eacf800027725891c2f668f2f0144)
This commit is contained in:
parent
f45543e2f8
commit
4f0f40e31e
9
event.c
9
event.c
@ -2749,17 +2749,16 @@ static int
|
||||
event_del_(struct event *ev, int blocking)
|
||||
{
|
||||
int res;
|
||||
struct event_base *base = ev->ev_base;
|
||||
|
||||
if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) {
|
||||
if (EVUTIL_FAILURE_CHECK(!base)) {
|
||||
event_warnx("%s: event has no event_base set.", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
|
||||
|
||||
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
|
||||
res = event_del_nolock_(ev, blocking);
|
||||
|
||||
EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
|
||||
EVBASE_RELEASE_LOCK(base, th_base_lock);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user