summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes7
-rw-r--r--ev.c78
-rw-r--r--ev_vars.h3
3 files changed, 43 insertions, 45 deletions
diff --git a/Changes b/Changes
index c7c026b..4fcd0c5 100644
--- a/Changes
+++ b/Changes
@@ -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
diff --git a/ev.c b/ev.c
index 09adac9..5885818 100644
--- a/ev.c
+++ b/ev.c
@@ -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;
}
diff --git a/ev_vars.h b/ev_vars.h
index 53bcfee..5fd9c7a 100644
--- a/ev_vars.h
+++ b/ev_vars.h
@@ -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)