On Tue, May 29, 2012 at 7:12 PM, Marc Lehmann <[email protected]> wrote:
> This one - your test program forks after initialising the default loop,
> without calling ev_default_fork.

OK, I've fixed the test program to do that and also fixed a fd leak.
It takes a bit longer to fail now, but it still fails.

> I added an ev_loop_destroy (EV_DEFAULT) at the end of test_main, and got a
> lot longer output, until:
>
> (libev) error creating signal/async pipe: Too many open files

With fd leak fixed, this should no longer happen. I've tried adding
ev_loop_destroy too - it still fails.

> Note that this only works because the fork isn't done while the default
> loop exists at the time - if you would fork while the dfeault loop
> existed, you'd have to work with ev_default_fork and probably stop all
> watchers you inherited form the parent.

At the time of fork there no active watchers in the test program.

> Now, the fork business is very unfortunate, but both epoll/kqueue and
> pthreads have diminished fork into a state where using an event loop in
> both parent ands child has become extreely hard (actually, doing anything
> in the child is hard with pthreads).

To rule out epoll issues, I'm now using EVBACKEND_SELECT explicitly -
still fails. There no pthreads either, so it has to be something else.

Attached is modified version with all the fixes mentioned above.
Please try it as well :) I've also tried using EVFLAG_FORKCHECK but
that did not help either.
/* gcc -DEV_STANDALONE=1 testsigchld.c -o testsigchld 
 *
 * Expected output: infinite sequence of *.*.*.......
 *
 * Actual output:
 *   denis@denis-laptop:~/work/libev-cvs$ ./testsigchld 
 *   *.*.*.Alarm clock
 *
 *   (number of iterations is different each time)
 *
 * */
#include "ev.c"


struct ev_child child;

void stop_child(struct ev_loop* loop, ev_child *w, int revents) {
    ev_child_stop(loop, w);
}

void stop_io(struct ev_loop* loop, ev_io *w, int revents) {
    ev_io_stop(loop, w);
}


void subprocess(void) {
    int pid;
    if (pid = fork()) {
        ev_child_init(&child, stop_child, pid, 0);
        ev_child_start(EV_DEFAULT, &child);
        ev_run(EV_DEFAULT, 0);
        fprintf(stderr, "*");
    }
    else {
        _exit(0);
    }
}


void test_main(void) {
    int pipefd[2];

    while (pipe(pipefd)) perror("pipe");

    int pid = fork();
    if (!pid) {
        ev_loop_fork(EV_DEFAULT);
        close(pipefd[0]);
        subprocess();
        write(pipefd[1], "k", 1);
        _exit(0);
    }

    close(pipefd[1]);
    alarm(5);
    
    struct ev_io io;
    ev_io_init(&io, stop_io, pipefd[0], 1);
    ev_io_start(EV_DEFAULT, &io);
    ev_run(EV_DEFAULT, 0);
    close(pipefd[0]);

    alarm(0);
}

int main(int argc, char** argv) {
    ev_default_loop(EVBACKEND_SELECT);
    while (1) {
        test_main();
        fprintf(stderr, ".");
    }
}
_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev

Reply via email to