Hello,

I am working on gevent/gipc and need to figure out why a libev signal watcher is still 'active' after destroying its originally assigned event loop. In the example code at the bottom of this mail, I

- create a signal watcher for SIGTERM
- assign it to the default event loop
- fork
- destroy the default event loop in the child
- create and run a new default event loop in the child
- send SIGTERM to the child

The output is:

Msg from parent with PID 9934
Msg from child with PID 9935
Waiting for child.
SIGTERM handler called in process 9935
Child finished, exit parent.

I infer from this that

- the signal handler is still installed in the child (not surprising, since it is inherited) - in the child, the signal watcher object is magically connected to the new loop

The latter surprises me. I went through the libev docs again and could not really find an explanation. Especially, I found this part:

"Destroying the default loop will "orphan" (not stop) all registered watchers, so you have to be careful not to execute code that modifies those watchers. Note also that in that case, you have to re-register any signal watchers."

What I indeed want is to "orphan" everything in the child related to the default loop created in the parent. However, it looks like signal watchers don't need to be re-registered, at least not for my test system. For some this might be a feature, but in my application case, this is a problem. I want to understand: why is that signal watcher still active?

And yes, an obvious solution would be `signal(SIGTERM, SIG_DFL);` in the child -- but what would the general approach be to make sure that previously installed watchers are not active anymore when their corresponding loop has been destroyed?


Thanks a lot for any insight,

Jan-Philip


The test program:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <ev.h>


void sigtermhandler(struct ev_loop *l, ev_signal *w, int revents) {
    printf("SIGTERM handler called in process %d\n", getpid());
    ev_break(l, EVBREAK_ALL);
}


void child(struct ev_loop *loop) {
    printf("Msg from child with PID %d\n", getpid());
    ev_loop_destroy(loop);

    // Reset signal handler:
    //signal(SIGTERM, SIG_DFL);

    struct ev_loop *newloop = ev_default_loop(0);
    ev_run(newloop, 0);
}


int main (void) {
    printf("Msg from parent with PID %d\n", getpid());
    struct ev_loop *loop = EV_DEFAULT;

    // Install signal watcher in parent, handling SIGTERM.
    ev_signal signal_watcher;
    ev_signal_init(&signal_watcher, sigtermhandler, SIGTERM);
    ev_signal_start(loop, &signal_watcher);

    pid_t  pid;
    pid = fork();
    if (pid == -1) {
        fprintf(stderr, "Can't fork, error %d\n", errno);
        exit(1);
    }
    else if (pid == 0) {
        child(loop);
        exit(0);
    }
    // Dirtywait until child is upnrunning, then send SIGTER.
    sleep(1);
    kill(pid, SIGTERM);
    //ev_run (loop, 0);
    printf("Waiting for child.\n");
    wait();
    printf("Child finished, exit parent.\n");
}

_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev

Reply via email to