X-Git-Url: https://git.llucax.com/software/libev.git/blobdiff_plain/b2ebd839862b60e3a71179138dd201e7c8a4fa61..2fde047707205b8d8f1c71482d2df57105217e17:/ev.c?ds=sidebyside diff --git a/ev.c b/ev.c index ffd19c6..8a09326 100644 --- a/ev.c +++ b/ev.c @@ -38,6 +38,8 @@ #include #include +#include +#include #include #include @@ -61,6 +63,7 @@ #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ #define MAX_BLOCKTIME 60. +#define PID_HASHSIZE 16 /* size of pid hahs table, must be power of two */ #include "ev.h" @@ -112,7 +115,13 @@ get_clock (void) #define array_needsize(base,cur,cnt,init) \ if ((cnt) > cur) \ { \ - int newcnt = cur ? cur << 1 : 16; \ + int newcnt = cur; \ + do \ + { \ + newcnt = (newcnt << 1) | 4 & ~3; \ + } \ + while ((cnt) > newcnt); \ + \ base = realloc (base, sizeof (*base) * (newcnt)); \ init (base + cur, newcnt - cur); \ cur = newcnt; \ @@ -190,7 +199,7 @@ queue_events (W *events, int eventcnt, int type) /* called on EBADF to verify fds */ static void -fd_recheck () +fd_recheck (void) { int fd; @@ -198,7 +207,10 @@ fd_recheck () if (anfds [fd].wev) if (fcntl (fd, F_GETFD) == -1 && errno == EBADF) while (anfds [fd].head) - evio_stop (anfds [fd].head); + { + event ((W)anfds [fd].head, EV_ERROR); + evio_stop (anfds [fd].head); + } } /*****************************************************************************/ @@ -334,6 +346,30 @@ static int checkmax, checkcnt; /*****************************************************************************/ +static struct ev_child *childs [PID_HASHSIZE]; +static struct ev_signal childev; + +#ifndef WCONTINUED +# define WCONTINUED 0 +#endif + +static void +childcb (struct ev_signal *sw, int revents) +{ + struct ev_child *w; + 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 == -1) + { + w->status = status; + event ((W)w, EV_CHILD); + } +} + +/*****************************************************************************/ + #if HAVE_EPOLL # include "ev_epoll.c" #endif @@ -341,35 +377,53 @@ static int checkmax, checkcnt; # include "ev_select.c" #endif +int +ev_version_major (void) +{ + return EV_VERSION_MAJOR; +} + +int +ev_version_minor (void) +{ + return EV_VERSION_MINOR; +} + int ev_init (int flags) { + if (!ev_method) + { #if HAVE_MONOTONIC - { - struct timespec ts; - if (!clock_gettime (CLOCK_MONOTONIC, &ts)) - have_monotonic = 1; - } + { + struct timespec ts; + if (!clock_gettime (CLOCK_MONOTONIC, &ts)) + have_monotonic = 1; + } #endif - ev_now = ev_time (); - now = get_clock (); - diff = ev_now - now; + ev_now = ev_time (); + now = get_clock (); + diff = ev_now - now; - if (pipe (sigpipe)) - return 0; + if (pipe (sigpipe)) + return 0; - ev_method = EVMETHOD_NONE; + ev_method = EVMETHOD_NONE; #if HAVE_EPOLL - if (ev_method == EVMETHOD_NONE) epoll_init (flags); + if (ev_method == EVMETHOD_NONE) epoll_init (flags); #endif #if HAVE_SELECT - if (ev_method == EVMETHOD_NONE) select_init (flags); + if (ev_method == EVMETHOD_NONE) select_init (flags); #endif - if (ev_method) - { - evw_init (&sigev, sigcb); - siginit (); + if (ev_method) + { + evw_init (&sigev, sigcb); + siginit (); + + evsignal_init (&childev, childcb, SIGCHLD); + evsignal_start (&childev); + } } return ev_method; @@ -377,17 +431,20 @@ int ev_init (int flags) /*****************************************************************************/ -void ev_prefork (void) +void +ev_prefork (void) { /* nop */ } -void ev_postfork_parent (void) +void +ev_postfork_parent (void) { /* nop */ } -void ev_postfork_child (void) +void +ev_postfork_child (void) { #if HAVE_EPOLL if (ev_method == EVMETHOD_EPOLL) @@ -430,7 +487,7 @@ fd_reify (void) } static void -call_pending () +call_pending (void) { while (pendingcnt) { @@ -445,7 +502,7 @@ call_pending () } static void -timers_reify () +timers_reify (void) { while (timercnt && timers [0]->at <= now) { @@ -466,7 +523,7 @@ timers_reify () } static void -periodics_reify () +periodics_reify (void) { while (periodiccnt && periodics [0]->at <= ev_now) { @@ -512,7 +569,7 @@ periodics_reschedule (ev_tstamp diff) } static void -time_update () +time_update (void) { int i; @@ -881,6 +938,25 @@ void evcheck_stop (struct ev_check *w) ev_stop ((W)w); } +void evchild_start (struct ev_child *w) +{ + if (ev_is_active (w)) + return; + + ev_start ((W)w, 1); + wlist_add ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w); +} + +void evchild_stop (struct ev_child *w) +{ + ev_clear ((W)w); + if (ev_is_active (w)) + return; + + wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w); + ev_stop ((W)w); +} + /*****************************************************************************/ struct ev_once