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