diff options
-rw-r--r-- | Changes | 7 | ||||
-rw-r--r-- | ev.c | 78 | ||||
-rw-r--r-- | ev_vars.h | 3 |
3 files changed, 43 insertions, 45 deletions
@@ -4,10 +4,12 @@ TODO: ev_loop_wakeup TODO: EV_STANDALONE == NO_HASSEL (do not use clock_gettime in ev_standalone) TODO: faq, process a thing in each iteration TODO: dbeugging tips, ev_verify, ev_init twice - +TODO: ev_break for immediate exit (EVBREAK_NOW?) TODO: ev_feed_child_event + TODO: document the special problem of signals around fork. TODO: store pid for each signal +TODO: document file descriptor usage per loop - destroying a non-default loop would stop the global waitpid watcher (Denis Bilenko). - queueing pending watchers of higher priority from a watcher now invokes @@ -41,6 +43,9 @@ TODO: store pid for each signal - work around recent glibc versions that leak memory in realloc. - rename ev::embed::set to ev::embed::set_embed to avoid clashing the watcher base set (loop) method. + - rewrite the async/signal pipe logic to always keep a valid fd, which + simplifies (and hopefuly correctifies :) the race checking + on fork, at the cost of one extra fd. 4.11 Sat Feb 4 19:52:39 CET 2012 - INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as @@ -1869,28 +1869,41 @@ evpipe_init (EV_P) { if (!ev_is_active (&pipe_w)) { + int fds [2]; + # if EV_USE_EVENTFD - evfd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC); - if (evfd < 0 && errno == EINVAL) - evfd = eventfd (0, 0); + fds [0] = -1; + fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC); + if (fds [1] < 0 && errno == EINVAL) + fds [1] = eventfd (0, 0); - if (evfd >= 0) + if (fds [1] < 0) +# endif { - evpipe [0] = -1; - fd_intern (evfd); /* doing it twice doesn't hurt */ - ev_io_set (&pipe_w, evfd, EV_READ); + while (pipe (fds)) + ev_syserr ("(libev) error creating signal/async pipe"); + + fd_intern (fds [0]); } + + fd_intern (fds [1]); + + evpipe [0] = fds [0]; + + if (evpipe [1] < 0) + evpipe [1] = fds [1]; /* first call, set write fd */ else -# endif { - while (pipe (evpipe)) - ev_syserr ("(libev) error creating signal/async pipe"); + /* on subsequent calls, do not change evpipe [1] */ + /* so that evpipe_write can always rely on its value. */ + /* this branch does not do anything sensible on windows, */ + /* so must not be executed on windows */ - fd_intern (evpipe [0]); - fd_intern (evpipe [1]); - ev_io_set (&pipe_w, evpipe [0], EV_READ); + dup2 (fds [1], evpipe [1]); + close (fds [1]); } + ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ); ev_io_start (EV_A_ &pipe_w); ev_unref (EV_A); /* watcher should not keep loop alive */ } @@ -1921,10 +1934,10 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag) old_errno = errno; /* save errno because write will clobber it */ #if EV_USE_EVENTFD - if (evfd >= 0) + if (evpipe [0] < 0) { uint64_t counter = 1; - write (evfd, &counter, sizeof (uint64_t)); + write (evpipe [1], &counter, sizeof (uint64_t)); } else #endif @@ -1954,10 +1967,10 @@ pipecb (EV_P_ ev_io *iow, int revents) if (revents & EV_READ) { #if EV_USE_EVENTFD - if (evfd >= 0) + if (evpipe [0] < 0) { uint64_t counter; - read (evfd, &counter, sizeof (uint64_t)); + read (evpipe [1], &counter, sizeof (uint64_t)); } else #endif @@ -2023,9 +2036,6 @@ ev_feed_signal (int signum) EV_THROW return; #endif - if (!ev_active (&pipe_w)) - return; - signals [signum - 1].pending = 1; evpipe_write (EV_A_ &sig_pending); } @@ -2353,6 +2363,8 @@ loop_init (EV_P_ unsigned int flags) EV_THROW #endif pipe_write_skipped = 0; pipe_write_wanted = 0; + evpipe [0] = -1; + evpipe [1] = -1; #if EV_USE_INOTIFY fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2; #endif @@ -2425,16 +2437,8 @@ ev_loop_destroy (EV_P) /*ev_ref (EV_A);*/ /*ev_io_stop (EV_A_ &pipe_w);*/ -#if EV_USE_EVENTFD - if (evfd >= 0) - close (evfd); -#endif - - if (evpipe [0] >= 0) - { - EV_WIN32_CLOSE_FD (evpipe [0]); - EV_WIN32_CLOSE_FD (evpipe [1]); - } + if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]); + if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]); } #if EV_USE_SIGNALFD @@ -2530,6 +2534,7 @@ loop_fork (EV_P) infy_fork (EV_A); #endif +#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE if (ev_is_active (&pipe_w)) { /* pipe_write_wanted must be false now, so modifying fd vars should be safe */ @@ -2537,23 +2542,14 @@ loop_fork (EV_P) ev_ref (EV_A); ev_io_stop (EV_A_ &pipe_w); -#if EV_USE_EVENTFD - if (evfd >= 0) - close (evfd); -#endif - if (evpipe [0] >= 0) - { - EV_WIN32_CLOSE_FD (evpipe [0]); - EV_WIN32_CLOSE_FD (evpipe [1]); - } + EV_WIN32_CLOSE_FD (evpipe [0]); -#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE evpipe_init (EV_A); /* iterate over everything, in case we missed something before */ ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); -#endif } +#endif postfork = 0; } @@ -69,9 +69,6 @@ VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout)) VARx(ANFD *, anfds) VARx(int, anfdmax) -#if EV_USE_EVENTFD || EV_GENWRAP -VARx(int, evfd) -#endif VAR (evpipe, int evpipe [2]) VARx(ev_io, pipe_w) VARx(EV_ATOMIC_T, pipe_write_wanted) |