--- libev/ev.c 2008/01/25 15:45:08 1.206 +++ libev/ev.c 2008/01/31 13:10:56 1.207 @@ -1,7 +1,7 @@ /* * libev event processing core, watcher management * - * Copyright (c) 2007 Marc Alexander Lehmann + * Copyright (c) 2007,2008 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -293,7 +293,7 @@ #if EV_USE_MONOTONIC /* sig_atomic_t is used to avoid per-thread variables or locking but still */ /* giving it a reasonably high chance of working on typical architetcures */ -static sig_atomic_t have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ +static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ #endif #ifdef _WIN32 @@ -765,15 +765,13 @@ typedef struct { WL head; - sig_atomic_t volatile gotsig; + EV_ATOMIC_T gotsig; } ANSIG; static ANSIG *signals; static int signalmax; -static int sigpipe [2]; -static sig_atomic_t volatile gotsig; -static ev_io sigev; +static EV_ATOMIC_T gotsig; void inline_size signals_init (ANSIG *base, int count) @@ -787,24 +785,101 @@ } } -static void -sighandler (int signum) +/*****************************************************************************/ + +void inline_speed +fd_intern (int fd) { -#if _WIN32 - signal (signum, sighandler); +#ifdef _WIN32 + int arg = 1; + ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg); +#else + fcntl (fd, F_SETFD, FD_CLOEXEC); + fcntl (fd, F_SETFL, O_NONBLOCK); #endif +} - signals [signum - 1].gotsig = 1; +static void noinline +evpipe_init (EV_P) +{ + if (!ev_is_active (&pipeev)) + { + while (pipe (evpipe)) + syserr ("(libev) error creating signal/async pipe"); + + fd_intern (evpipe [0]); + fd_intern (evpipe [1]); + + ev_io_set (&pipeev, evpipe [0], EV_READ); + ev_io_start (EV_A_ &pipeev); + ev_unref (EV_A); /* child watcher should not keep loop alive */ + } +} - if (!gotsig) +void inline_size +evpipe_write (EV_P_ int sig, int async) +{ + if (!(gotasync || gotsig)) { int old_errno = errno; - gotsig = 1; - write (sigpipe [1], &signum, 1); + + if (sig) gotsig = 1; + if (async) gotasync = 1; + + write (evpipe [1], &old_errno, 1); errno = old_errno; } } +static void +pipecb (EV_P_ ev_io *iow, int revents) +{ + { + int dummy; + read (evpipe [0], &dummy, 1); + } + + if (gotsig) + { + int signum; + gotsig = 0; + + for (signum = signalmax; signum--; ) + if (signals [signum].gotsig) + ev_feed_signal_event (EV_A_ signum + 1); + } + + if (gotasync) + { + int i; + gotasync = 0; + + for (i = asynccnt; i--; ) + if (asyncs [i]->sent) + { + asyncs [i]->sent = 0; + ev_feed_event (EV_A_ asyncs [i], EV_ASYNC); + } + } +} + +/*****************************************************************************/ + +static void +sighandler (int signum) +{ +#if EV_MULTIPLICITY + struct ev_loop *loop = &default_loop_struct; +#endif + +#if _WIN32 + signal (signum, sighandler); +#endif + + signals [signum - 1].gotsig = 1; + evpipe_write (EV_A_ 1, 0); +} + void noinline ev_feed_signal_event (EV_P_ int signum) { @@ -825,42 +900,6 @@ ev_feed_event (EV_A_ (W)w, EV_SIGNAL); } -static void -sigcb (EV_P_ ev_io *iow, int revents) -{ - int signum; - - read (sigpipe [0], &revents, 1); - gotsig = 0; - - for (signum = signalmax; signum--; ) - if (signals [signum].gotsig) - ev_feed_signal_event (EV_A_ signum + 1); -} - -void inline_speed -fd_intern (int fd) -{ -#ifdef _WIN32 - int arg = 1; - ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg); -#else - fcntl (fd, F_SETFD, FD_CLOEXEC); - fcntl (fd, F_SETFL, O_NONBLOCK); -#endif -} - -static void noinline -siginit (EV_P) -{ - fd_intern (sigpipe [0]); - fd_intern (sigpipe [1]); - - ev_io_set (&sigev, sigpipe [0], EV_READ); - ev_io_start (EV_A_ &sigev); - ev_unref (EV_A); /* child watcher should not keep loop alive */ -} - /*****************************************************************************/ static WL childs [EV_PID_HASHSIZE]; @@ -1086,8 +1125,8 @@ if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags); #endif - ev_init (&sigev, sigcb); - ev_set_priority (&sigev, EV_MAXPRI); + ev_init (&pipeev, pipecb); + ev_set_priority (&pipeev, EV_MAXPRI); } } @@ -1096,6 +1135,15 @@ { int i; + if (ev_is_active (&pipeev)) + { + ev_ref (EV_A); /* signal watcher */ + ev_io_stop (EV_A_ &pipeev); + + close (evpipe [0]); evpipe [0] = 0; + close (evpipe [1]); evpipe [1] = 0; + } + #if EV_USE_INOTIFY if (fs_fd >= 0) close (fs_fd); @@ -1163,20 +1211,19 @@ infy_fork (EV_A); #endif - if (ev_is_active (&sigev)) + if (ev_is_active (&pipeev)) { - /* default loop */ + /* this "locks" the handlers against writing to the pipe */ + gotsig = gotasync = 1; ev_ref (EV_A); - ev_io_stop (EV_A_ &sigev); - close (sigpipe [0]); - close (sigpipe [1]); - - while (pipe (sigpipe)) - syserr ("(libev) error creating pipe"); - - siginit (EV_A); - sigcb (EV_A_ &sigev, EV_READ); + ev_io_stop (EV_A_ &pipeev); + close (evpipe [0]); + close (evpipe [1]); + + evpipe_init (EV_A); + /* now iterate over everything */ + evcb (EV_A_ &pipeev, EV_READ); } postfork = 0; @@ -1221,10 +1268,6 @@ ev_default_loop (unsigned int flags) #endif { - if (sigpipe [0] == sigpipe [1]) - if (pipe (sigpipe)) - return 0; - if (!ev_default_loop_ptr) { #if EV_MULTIPLICITY @@ -1237,8 +1280,6 @@ if (ev_backend (EV_A)) { - siginit (EV_A); - #ifndef _WIN32 ev_signal_init (&childev, childcb, SIGCHLD); ev_set_priority (&childev, EV_MAXPRI); @@ -1265,12 +1306,6 @@ ev_signal_stop (EV_A_ &childev); #endif - ev_ref (EV_A); /* signal watcher */ - ev_io_stop (EV_A_ &sigev); - - close (sigpipe [0]); sigpipe [0] = 0; - close (sigpipe [1]); sigpipe [1] = 0; - loop_destroy (EV_A); } @@ -1867,6 +1902,8 @@ assert (("ev_signal_start called with illegal signal number", w->signum > 0)); + evpipe_init (EV_A); + { #ifndef _WIN32 sigset_t full, prev; @@ -2389,6 +2426,44 @@ } #endif +#if EV_ASYNC_ENABLE +void +ev_async_start (EV_P_ ev_async *w) +{ + if (expect_false (ev_is_active (w))) + return; + + evpipe_init (EV_A); + + ev_start (EV_A_ (W)w, ++asynccnt); + array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2); + asyncs [asynccnt - 1] = w; +} + +void +ev_async_stop (EV_P_ ev_async *w) +{ + clear_pending (EV_A_ (W)w); + if (expect_false (!ev_is_active (w))) + return; + + { + int active = ((W)w)->active; + asyncs [active - 1] = asyncs [--asynccnt]; + ((W)asyncs [active - 1])->active = active; + } + + ev_stop (EV_A_ (W)w); +} + +void +ev_async_send (EV_P_ ev_async *w) +{ + w->sent = 1; + evpipe_write (EV_A_ 0, 1); +} +#endif + /*****************************************************************************/ struct ev_once