X-Git-Url: https://git.llucax.com/software/libev.git/blobdiff_plain/92dcada736d22a0f8f2ed4351713c0299db32138..ba71cf07f3506b8e303130e981d3b5b3e9ea5dc8:/ev.c?ds=sidebyside diff --git a/ev.c b/ev.c index 8c1337f..40e2292 100644 --- a/ev.c +++ b/ev.c @@ -200,7 +200,7 @@ extern "C" { #else # define expect(expr,value) (expr) # define inline_speed static -# define inline_minimal static +# define inline_size static # define noinline #endif @@ -717,10 +717,6 @@ static ev_child *childs [PID_HASHSIZE]; static ev_signal childev; -#ifndef WCONTINUED -# define WCONTINUED 0 -#endif - void inline_speed child_reap (EV_P_ ev_signal *sw, int chain, int pid, int status) { @@ -736,20 +732,28 @@ child_reap (EV_P_ ev_signal *sw, int chain, int pid, int status) } } +#ifndef WCONTINUED +# define WCONTINUED 0 +#endif + static void childcb (EV_P_ ev_signal *sw, int revents) { int pid, status; - if (0 < (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED))) - { - /* make sure we are called again until all childs have been reaped */ - /* we need to do it this way so that the callback gets called before we continue */ - ev_feed_event (EV_A_ (W)sw, EV_SIGNAL); + /* some systems define WCONTINUED but then fail to support it (linux 2.4) */ + if (0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED))) + if (!WCONTINUED + || errno != EINVAL + || 0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED))) + return; - child_reap (EV_A_ sw, pid, pid, status); - child_reap (EV_A_ sw, 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */ - } + /* make sure we are called again until all childs have been reaped */ + /* we need to do it this way so that the callback gets called before we continue */ + ev_feed_event (EV_A_ (W)sw, EV_SIGNAL); + + child_reap (EV_A_ sw, pid, pid, status); + child_reap (EV_A_ sw, 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */ } #endif @@ -1556,73 +1560,158 @@ ev_periodic_again (EV_P_ ev_periodic *w) } #endif +#ifndef SA_RESTART +# define SA_RESTART 0 +#endif + void -ev_idle_start (EV_P_ ev_idle *w) +ev_signal_start (EV_P_ ev_signal *w) { +#if EV_MULTIPLICITY + assert (("signal watchers are only supported in the default loop", loop == ev_default_loop_ptr)); +#endif if (expect_false (ev_is_active (w))) return; - ev_start (EV_A_ (W)w, ++idlecnt); - array_needsize (ev_idle *, idles, idlemax, idlecnt, EMPTY2); - idles [idlecnt - 1] = w; + assert (("ev_signal_start called with illegal signal number", w->signum > 0)); + + ev_start (EV_A_ (W)w, 1); + array_needsize (ANSIG, signals, signalmax, w->signum, signals_init); + wlist_add ((WL *)&signals [w->signum - 1].head, (WL)w); + + if (!((WL)w)->next) + { +#if _WIN32 + signal (w->signum, sighandler); +#else + struct sigaction sa; + sa.sa_handler = sighandler; + sigfillset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */ + sigaction (w->signum, &sa, 0); +#endif + } } void -ev_idle_stop (EV_P_ ev_idle *w) +ev_signal_stop (EV_P_ ev_signal *w) { ev_clear_pending (EV_A_ (W)w); if (expect_false (!ev_is_active (w))) return; - { - int active = ((W)w)->active; - idles [active - 1] = idles [--idlecnt]; - ((W)idles [active - 1])->active = active; - } + wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w); + ev_stop (EV_A_ (W)w); + if (!signals [w->signum - 1].head) + signal (w->signum, SIG_DFL); +} + +void +ev_child_start (EV_P_ ev_child *w) +{ +#if EV_MULTIPLICITY + assert (("child watchers are only supported in the default loop", loop == ev_default_loop_ptr)); +#endif + if (expect_false (ev_is_active (w))) + return; + + ev_start (EV_A_ (W)w, 1); + wlist_add ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w); +} + +void +ev_child_stop (EV_P_ ev_child *w) +{ + ev_clear_pending (EV_A_ (W)w); + if (expect_false (!ev_is_active (w))) + return; + + wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w); ev_stop (EV_A_ (W)w); } +#if EV_STAT_ENABLE + +# ifdef _WIN32 +# undef lstat +# define lstat(a,b) _stati64 (a,b) +# endif + +#define DEF_STAT_INTERVAL 5.0074891 +#define MIN_STAT_INTERVAL 0.1074891 + void -ev_prepare_start (EV_P_ ev_prepare *w) +ev_stat_stat (EV_P_ ev_stat *w) +{ + if (lstat (w->path, &w->attr) < 0) + w->attr.st_nlink = 0; + else if (!w->attr.st_nlink) + w->attr.st_nlink = 1; +} + +static void +stat_timer_cb (EV_P_ ev_timer *w_, int revents) +{ + ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer)); + + /* we copy this here each the time so that */ + /* prev has the old value when the callback gets invoked */ + w->prev = w->attr; + ev_stat_stat (EV_A_ w); + + if (memcmp (&w->prev, &w->attr, sizeof (ev_statdata))) + ev_feed_event (EV_A_ w, EV_STAT); +} + +void +ev_stat_start (EV_P_ ev_stat *w) { if (expect_false (ev_is_active (w))) return; - ev_start (EV_A_ (W)w, ++preparecnt); - array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2); - prepares [preparecnt - 1] = w; + /* since we use memcmp, we need to clear any padding data etc. */ + memset (&w->prev, 0, sizeof (ev_statdata)); + memset (&w->attr, 0, sizeof (ev_statdata)); + + ev_stat_stat (EV_A_ w); + + if (w->interval < MIN_STAT_INTERVAL) + w->interval = w->interval ? MIN_STAT_INTERVAL : DEF_STAT_INTERVAL; + + ev_timer_init (&w->timer, stat_timer_cb, w->interval, w->interval); + ev_set_priority (&w->timer, ev_priority (w)); + ev_timer_start (EV_A_ &w->timer); + + ev_start (EV_A_ (W)w, 1); } void -ev_prepare_stop (EV_P_ ev_prepare *w) +ev_stat_stop (EV_P_ ev_stat *w) { ev_clear_pending (EV_A_ (W)w); if (expect_false (!ev_is_active (w))) return; - { - int active = ((W)w)->active; - prepares [active - 1] = prepares [--preparecnt]; - ((W)prepares [active - 1])->active = active; - } + ev_timer_stop (EV_A_ &w->timer); ev_stop (EV_A_ (W)w); } +#endif void -ev_check_start (EV_P_ ev_check *w) +ev_idle_start (EV_P_ ev_idle *w) { if (expect_false (ev_is_active (w))) return; - ev_start (EV_A_ (W)w, ++checkcnt); - array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2); - checks [checkcnt - 1] = w; + ev_start (EV_A_ (W)w, ++idlecnt); + array_needsize (ev_idle *, idles, idlemax, idlecnt, EMPTY2); + idles [idlecnt - 1] = w; } void -ev_check_stop (EV_P_ ev_check *w) +ev_idle_stop (EV_P_ ev_idle *w) { ev_clear_pending (EV_A_ (W)w); if (expect_false (!ev_is_active (w))) @@ -1630,81 +1719,64 @@ ev_check_stop (EV_P_ ev_check *w) { int active = ((W)w)->active; - checks [active - 1] = checks [--checkcnt]; - ((W)checks [active - 1])->active = active; + idles [active - 1] = idles [--idlecnt]; + ((W)idles [active - 1])->active = active; } ev_stop (EV_A_ (W)w); } -#ifndef SA_RESTART -# define SA_RESTART 0 -#endif - void -ev_signal_start (EV_P_ ev_signal *w) +ev_prepare_start (EV_P_ ev_prepare *w) { -#if EV_MULTIPLICITY - assert (("signal watchers are only supported in the default loop", loop == ev_default_loop_ptr)); -#endif if (expect_false (ev_is_active (w))) return; - assert (("ev_signal_start called with illegal signal number", w->signum > 0)); - - ev_start (EV_A_ (W)w, 1); - array_needsize (ANSIG, signals, signalmax, w->signum, signals_init); - wlist_add ((WL *)&signals [w->signum - 1].head, (WL)w); - - if (!((WL)w)->next) - { -#if _WIN32 - signal (w->signum, sighandler); -#else - struct sigaction sa; - sa.sa_handler = sighandler; - sigfillset (&sa.sa_mask); - sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */ - sigaction (w->signum, &sa, 0); -#endif - } + ev_start (EV_A_ (W)w, ++preparecnt); + array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2); + prepares [preparecnt - 1] = w; } void -ev_signal_stop (EV_P_ ev_signal *w) +ev_prepare_stop (EV_P_ ev_prepare *w) { ev_clear_pending (EV_A_ (W)w); if (expect_false (!ev_is_active (w))) return; - wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w); - ev_stop (EV_A_ (W)w); + { + int active = ((W)w)->active; + prepares [active - 1] = prepares [--preparecnt]; + ((W)prepares [active - 1])->active = active; + } - if (!signals [w->signum - 1].head) - signal (w->signum, SIG_DFL); + ev_stop (EV_A_ (W)w); } void -ev_child_start (EV_P_ ev_child *w) +ev_check_start (EV_P_ ev_check *w) { -#if EV_MULTIPLICITY - assert (("child watchers are only supported in the default loop", loop == ev_default_loop_ptr)); -#endif if (expect_false (ev_is_active (w))) return; - ev_start (EV_A_ (W)w, 1); - wlist_add ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w); + ev_start (EV_A_ (W)w, ++checkcnt); + array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2); + checks [checkcnt - 1] = w; } void -ev_child_stop (EV_P_ ev_child *w) +ev_check_stop (EV_P_ ev_check *w) { ev_clear_pending (EV_A_ (W)w); if (expect_false (!ev_is_active (w))) return; - wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w); + { + int active = ((W)w)->active; + checks [active - 1] = checks [--checkcnt]; + ((W)checks [active - 1])->active = active; + } + ev_stop (EV_A_ (W)w); } @@ -1757,67 +1829,6 @@ ev_embed_stop (EV_P_ ev_embed *w) } #endif -#if EV_STAT_ENABLE - -# ifdef _WIN32 -# define lstat(a,b) stat(a,b) -# endif - -void -ev_stat_stat (EV_P_ ev_stat *w) -{ - if (lstat (w->path, &w->attr) < 0) - w->attr.st_nlink = 0; - else if (!w->attr.st_nlink) - w->attr.st_nlink = 1; -} - -static void -stat_timer_cb (EV_P_ ev_timer *w_, int revents) -{ - ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer)); - - /* we copy this here each the time so that */ - /* prev has the old value when the callback gets invoked */ - w->prev = w->attr; - ev_stat_stat (EV_A_ w); - - if (memcmp (&w->prev, &w->attr, sizeof (ev_statdata))) - ev_feed_event (EV_A_ w, EV_STAT); -} - -void -ev_stat_start (EV_P_ ev_stat *w) -{ - if (expect_false (ev_is_active (w))) - return; - - /* since we use memcmp, we need to clear any padding data etc. */ - memset (&w->prev, 0, sizeof (ev_statdata)); - memset (&w->attr, 0, sizeof (ev_statdata)); - - ev_stat_stat (EV_A_ w); - - ev_timer_init (&w->timer, stat_timer_cb, w->interval, w->interval); - ev_set_priority (&w->timer, ev_priority (w)); - ev_timer_start (EV_A_ &w->timer); - - ev_start (EV_A_ (W)w, 1); -} - -void -ev_stat_stop (EV_P_ ev_stat *w) -{ - ev_clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - ev_timer_stop (EV_A_ &w->timer); - - ev_stop (EV_A_ (W)w); -} -#endif - /*****************************************************************************/ struct ev_once