Close th_notify_fds and open a new pair on reinit

After a fork, you want subthreads to wake up the event_base in the
child process, not to have the child process and the main process
fight over who wakes up whom.

Related to a problem found by Nicholas Marriott while debugging
3048812.
This commit is contained in:
Nick Mathewson 2010-09-01 16:36:30 -04:00
parent acc4aca49e
commit 495ed66705

21
event.c
View File

@ -742,6 +742,7 @@ event_reinit(struct event_base *base)
const struct eventop *evsel;
int res = 0;
struct event *ev;
int was_notifiable = 0;
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
@ -769,6 +770,23 @@ event_reinit(struct event_base *base)
EVLIST_ACTIVE);
base->sig.ev_signal_added = 0;
}
if (base->th_notify_fd[0] != -1) {
/* we cannot call event_del here because the base has
* not been reinitialized yet. */
was_notifiable = 1;
event_queue_remove(base, &base->th_notify,
EVLIST_INSERTED);
if (base->th_notify.ev_flags & EVLIST_ACTIVE)
event_queue_remove(base, &base->th_notify,
EVLIST_ACTIVE);
base->sig.ev_signal_added = 0;
EVUTIL_CLOSESOCKET(base->th_notify_fd[0]);
if (base->th_notify_fd[1] != -1)
EVUTIL_CLOSESOCKET(base->th_notify_fd[1]);
base->th_notify_fd[0] = -1;
base->th_notify_fd[1] = -1;
event_debug_unassign(&base->th_notify);
}
if (base->evsel->dealloc != NULL)
base->evsel->dealloc(base);
@ -794,6 +812,9 @@ event_reinit(struct event_base *base)
}
}
if (was_notifiable && res == 0)
res = evthread_make_base_notifiable(base);
done:
EVBASE_RELEASE_LOCK(base, th_base_lock);
return (res);