hi

libevent has this clever stuff to reinitialise signals if the backend
requires it after calling event_reinit() (typically called after
fork()).

unfortunately, it isn't enabled for poll and select, so both parent and
child continue to use the same socketpair for signals.

one byte is written into this socketpair to wake up the main event loop
on a signal, so there is an occasional race between the processes to
read this byte, causing the losing process to hang, blocked in recv().

this problem was seen by kili@ during the period tmux was switched to
poll, i'm pretty surprised others didn't see it as well.

this is the fix upstream have decided to go with for now, enabling the
reinit code for all backends (all but poll and select already use it).

ok?


Index: event.c
===================================================================
RCS file: /cvs/src/lib/libevent/event.c,v
retrieving revision 1.24
diff -u -p -r1.24 event.c
--- event.c     12 Jul 2010 18:03:38 -0000      1.24
+++ event.c     26 Aug 2010 19:57:53 -0000
@@ -281,9 +281,14 @@ event_reinit(struct event_base *base)
        int res = 0;
        struct event *ev;
 
+#if 0
+       /* Right now, reinit always takes effect, since even if the
+          backend doesn't require it, the signal socketpair code does.
+       */
        /* check if this event mechanism requires reinit */
        if (!evsel->need_reinit)
                return (0);
+#endif
 
        /* prevent internal delete */
        if (base->sig.ev_signal_added) {
@@ -296,7 +301,7 @@ event_reinit(struct event_base *base)
                            EVLIST_ACTIVE);
                base->sig.ev_signal_added = 0;
        }
-       
+
        if (base->evsel->dealloc != NULL)
                base->evsel->dealloc(base, base->evbase);
        evbase = base->evbase = evsel->init(base);

Reply via email to