]> granicus.if.org Git - libevent/commitdiff
Close th_notify_fds and open a new pair on reinit
authorNick Mathewson <nickm@torproject.org>
Wed, 1 Sep 2010 20:36:30 +0000 (16:36 -0400)
committerNick Mathewson <nickm@torproject.org>
Thu, 2 Sep 2010 15:00:27 +0000 (11:00 -0400)
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.

event.c

diff --git a/event.c b/event.c
index dbf1c2f340b34e3f1e77b7ad4e30a7ca798cab47..ee741e7beae18d6d3f3da70f4badd4fa848b437d 100644 (file)
--- a/event.c
+++ b/event.c
@@ -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);