mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 04:50:37 -04:00
Fix a deadlock related to event-base notification. Diagnosed by Zhou Li, Avi Bab, and Scott Lamb.
The problem was that the thread doing the notification could block on write in evthread_notify_base_default while holding the th_base_lock. The main thread would never drain th_notify_fd[0], since it would need th_base_lock to actually trigger events.
This commit is contained in:
parent
d89fdba424
commit
17522d2af8
13
event.c
13
event.c
@ -1835,7 +1835,7 @@ evthread_notify_base_default(struct event_base *base)
|
|||||||
#else
|
#else
|
||||||
r = write(base->th_notify_fd[1], buf, 1);
|
r = write(base->th_notify_fd[1], buf, 1);
|
||||||
#endif
|
#endif
|
||||||
return (r < 0) ? -1 : 0;
|
return (r < 0 && errno != EAGAIN) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_EVENT_HAVE_EVENTFD) && defined(_EVENT_HAVE_SYS_EVENTFD_H)
|
#if defined(_EVENT_HAVE_EVENTFD) && defined(_EVENT_HAVE_SYS_EVENTFD_H)
|
||||||
@ -2594,10 +2594,15 @@ evthread_make_base_notifiable(struct event_base *base)
|
|||||||
base->th_notify_fn = notify;
|
base->th_notify_fn = notify;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This can't be right, can it? We want writes to this socket to
|
Making the second socket nonblocking is a bit subtle, given that we
|
||||||
just succeed.
|
ignore any EAGAIN returns when writing to it, and you don't usally
|
||||||
evutil_make_socket_nonblocking(base->th_notify_fd[1]);
|
do that for a nonblocking socket. But if the kernel gives us EAGAIN,
|
||||||
|
then there's no need to add any more data to the buffer, since
|
||||||
|
the main thread is already either about to wake up and drain it,
|
||||||
|
or woken up and in the process of draining it.
|
||||||
*/
|
*/
|
||||||
|
if (base->th_notify_fd[1] > 0)
|
||||||
|
evutil_make_socket_nonblocking(base->th_notify_fd[1]);
|
||||||
|
|
||||||
/* prepare an event that we can use for wakeup */
|
/* prepare an event that we can use for wakeup */
|
||||||
event_assign(&base->th_notify, base, base->th_notify_fd[0],
|
event_assign(&base->th_notify, base, base->th_notify_fd[0],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user