#350 2.1.5-beta, signals and event_reinit

For_1.4
open
nobody
None
5
2015-04-07
2015-04-07
No

Hi hi

The test program attached works with 2.0.22 but does not with 2.1.5. It looks like the signal socketpair event in the child is never fired (it does not get as far as trying to read).

I've tried it on Linux but also some reports that the same problem appears on OS X (it affects tmux).

The actual signal doesn't seem to matter. I've use USR1 here, in tmux it is CHLD.

$ CPPFLAGS='-I/opt/libevent20/include' LDFLAGS='-L/opt/libevent20/lib -levent' make test-reinit
$ ./test-reinit
sending signal
got signal
$

$ CPPFLAGS='-I/opt/libevent21/include' LDFLAGS='-L/opt/libevent21/lib -levent' make test-reinit
$ ./test-reinit
sending signal
$

1 Attachments

Discussion

  • Anonymous - 2015-04-07

    Hmm. I can't reproduce on a different Ubuntu box; works on a 2-core, fails on 4-core, can't see any other obvious differences. Both:

    Linux macbook-air 3.13.0-48-generic #80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

    But tmux definitely fails on both, so I guess my test program is not complete.

     
  • Anonymous - 2015-04-07

    Ok, please ignore my test program, it is bollocks. I had some debug code in libevent that was messing it up.

    But I think I have found the actual problem.

    event_reinit isn't doing the right thing for non-reinit backends.

    It only closes the signal socketpair fds and recreates them if signals have been added, but this is wrong - the parent could add signals AFTER event_reinit is called in the child.

    For non-reinit backends, this will use the same socketpair because the child didn't create a new one (because there were no signals added before event_reinit).

    So event_reinit should ALWAYS call evsig_init_ for non-reinit backends (reinit backends will do it anyway in their init function).

    Also, for non-reinit backends, event_reinit removes the event, but only evsig_add puts it back. So it seems as if any signals set up before event_reinit will be ignored until another signal is added.

    Only the first part affects tmux but this diff fixes them both:

    diff --git a/event.c b/event.c
    index acef2b2..ad4c7f0 100644
    --- a/event.c
    +++ b/event.c
    @@ -926,13 +926,13 @@ event_reinit(struct event_base *base)
            event_del_nolock_(&base->sig.ev_signal, EVENT_DEL_AUTOBLOCK);
            event_debug_unassign(&base->sig.ev_signal);
            memset(&base->sig.ev_signal, 0, sizeof(base->sig.ev_signal));
    -       if (base->sig.ev_signal_pair[0] != -1)
    -           EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
    -       if (base->sig.ev_signal_pair[1] != -1)
    -           EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
            had_signal_added = 1;
            base->sig.ev_signal_added = 0;
        }
    +    if (base->sig.ev_signal_pair[0] != -1)
    +        EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
    +    if (base->sig.ev_signal_pair[1] != -1)
    +        EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
        if (base->th_notify_fn != NULL) {
            was_notifiable = 1;
            base->th_notify_fn = NULL;
    @@ -981,8 +981,12 @@ event_reinit(struct event_base *base)
            if (evmap_reinit_(base) < 0)
                res = -1;
        } else {
    -       if (had_signal_added)
                res = evsig_init_(base);
    +           if (res == 0 && had_signal_added) {
    +               res = event_add_nolock_(&base->sig.ev_signal, NULL, 0);
    +               if (res == 0)
    +                   base->sig.ev_signal_added = 1;
    +           }
        }
    
        /* If we were notifiable before, and nothing just exploded, become
    
     
  • Anonymous - 2015-04-07

    Diff as attachment.

     
  • Anonymous - 2015-04-07

    Here's a test program that actually works and demonstrates the first problem (signals added in parent after child calls event_reinit):

    $ ./test-reinit2
    sending signal
    child signal
    ^C
    $ ./test-reinit2
    sending signal
    child signal
    ^C
    $ ./test-reinit2
    sending signal
    PARENT signal
    ^C
    $

     
  • Anonymous - 2015-04-07

    Here's a program that shows the second problem, if signals are added in the parent before fork, they are not received in the child after event_reinit. The diff above also fixes this.

    Wrong output:

    $ ./test-reinit3
    sending signal
    ^C
    $

    Correct output:

    $ ./test-reinit3
    sending signal
    PARENT signal
    ^C
    $

    (Note even though it says PARENT the signal is being sent to and the callback is being fired in the child; it just sets the signal event up in the parent.)

     
    Last edit: Anonymous 2015-04-07

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks