X-Git-Url: https://git.llucax.com/software/libev.git/blobdiff_plain/8ee8df9cf84f6ae595eb82ebe7e5eb119112087e..34a787b55768ddae6645862dc60434188e1fad8d:/ev.c?ds=sidebyside diff --git a/ev.c b/ev.c index cca3a3d..3e1e8b4 100644 --- a/ev.c +++ b/ev.c @@ -44,7 +44,9 @@ #include #include #include -#include +#ifndef WIN32 +# include +#endif #include #include @@ -413,8 +415,10 @@ sighandler (int signum) if (!gotsig) { + int old_errno = errno; gotsig = 1; write (sigpipe [1], &signum, 1); + errno = old_errno; } } @@ -440,12 +444,14 @@ sigcb (struct ev_io *iow, int revents) static void siginit (void) { +#ifndef WIN32 fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC); fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC); /* rather than sort out wether we really need nb, set it */ fcntl (sigpipe [0], F_SETFL, O_NONBLOCK); fcntl (sigpipe [1], F_SETFL, O_NONBLOCK); +#endif ev_io_set (&sigev, sigpipe [0], EV_READ); ev_io_start (&sigev); @@ -467,25 +473,46 @@ static int checkmax, checkcnt; static struct ev_child *childs [PID_HASHSIZE]; static struct ev_signal childev; +#ifndef WIN32 + #ifndef WCONTINUED # define WCONTINUED 0 #endif static void -childcb (struct ev_signal *sw, int revents) +child_reap (struct ev_signal *sw, int chain, int pid, int status) { struct ev_child *w; + + for (w = childs [chain & (PID_HASHSIZE - 1)]; w; w = w->next) + if (w->pid == pid || !w->pid) + { + w->priority = sw->priority; /* need to do it *now* */ + w->rpid = pid; + w->rstatus = status; + printf ("rpid %p %d %d\n", w, pid, w->pid);//D + event ((W)w, EV_CHILD); + } +} + +static void +childcb (struct ev_signal *sw, int revents) +{ int pid, status; - while ((pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)) != -1) - for (w = childs [pid & (PID_HASHSIZE - 1)]; w; w = w->next) - if (w->pid == pid || !w->pid) - { - w->status = status; - event ((W)w, EV_CHILD); - } + printf ("chld %x\n", revents);//D + if (0 < (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED))) + { + /* make sure we are called again until all childs have been reaped */ + event ((W)sw, EV_SIGNAL); + + child_reap (sw, pid, pid, status); + child_reap (sw, 0, pid, status); /* this might trigger a watcher twice, but event catches that */ + } } +#endif + /*****************************************************************************/ #if EV_USE_KQUEUE @@ -513,12 +540,16 @@ ev_version_minor (void) return EV_VERSION_MINOR; } -/* return true if we are running with elevated privileges and ignore env variables */ +/* return true if we are running with elevated privileges and should ignore env variables */ static int enable_secure () { +#ifdef WIN32 + return 0; +#else return getuid () != geteuid () || getgid () != getegid (); +#endif } int ev_init (int methods) @@ -564,10 +595,14 @@ int ev_init (int methods) if (ev_method) { ev_watcher_init (&sigev, sigcb); + ev_set_priority (&sigev, EV_MAXPRI); siginit (); +#ifndef WIN32 ev_signal_init (&childev, childcb, SIGCHLD); + ev_set_priority (&childev, EV_MAXPRI); ev_signal_start (&childev); +#endif } } @@ -999,6 +1034,10 @@ ev_periodic_stop (struct ev_periodic *w) ev_stop ((W)w); } +#ifndef SA_RESTART +# define SA_RESTART 0 +#endif + void ev_signal_start (struct ev_signal *w) { @@ -1016,7 +1055,7 @@ ev_signal_start (struct ev_signal *w) struct sigaction sa; sa.sa_handler = sighandler; sigfillset (&sa.sa_mask); - sa.sa_flags = 0; + sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */ sigaction (w->signum, &sa, 0); } }