summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <root>2007-11-06 00:52:32 +0000
committerroot <root>2007-11-06 00:52:32 +0000
commit499c7e995433fedd0a2333ec6d9bc3768e6224f4 (patch)
tree63804fd270e45b25889a1d3a380e3912ada25a4b
parentdeff62d26ff4c1324816c04c0c6db1e4db435870 (diff)
better fork
-rw-r--r--ev.c60
-rw-r--r--ev.h2
-rw-r--r--ev_epoll.c13
-rw-r--r--ev_kqueue.c13
-rw-r--r--ev_poll.c2
-rw-r--r--ev_select.c2
-rw-r--r--ev_vars.h1
7 files changed, 64 insertions, 29 deletions
diff --git a/ev.c b/ev.c
index c12037c..0457088 100644
--- a/ev.c
+++ b/ev.c
@@ -155,21 +155,24 @@ volatile double SIGFPE_REQ = 0.0f;
/*****************************************************************************/
-static void (*syserr_cb)(void);
+static void (*syserr_cb)(const char *msg);
-void ev_set_syserr_cb (void (*cb)(void))
+void ev_set_syserr_cb (void (*cb)(const char *msg))
{
syserr_cb = cb;
}
static void
-syserr (void)
+syserr (const char *msg)
{
+ if (!msg)
+ msg = "(libev) system error";
+
if (syserr_cb)
- syserr_cb ();
+ syserr_cb (msg);
else
{
- perror ("libev");
+ perror (msg);
abort ();
}
}
@@ -380,7 +383,7 @@ fd_reify (EV_P)
static void
fd_change (EV_P_ int fd)
{
- if (anfds [fd].reify || fdchangecnt < 0)
+ if (anfds [fd].reify)
return;
anfds [fd].reify = 1;
@@ -428,7 +431,7 @@ fd_enomem (EV_P)
}
}
-/* susually called after fork if method needs to re-arm all fds from scratch */
+/* usually called after fork if method needs to re-arm all fds from scratch */
static void
fd_rearm_all (EV_P)
{
@@ -695,6 +698,9 @@ loop_init (EV_P_ int methods)
#if EV_USE_SELECT
if (!method && (methods & EVMETHOD_SELECT)) method = select_init (EV_A_ methods);
#endif
+
+ ev_watcher_init (&sigev, sigcb);
+ ev_set_priority (&sigev, EV_MAXPRI);
}
}
@@ -730,19 +736,34 @@ loop_destroy (EV_P)
array_free (check, );
method = 0;
- /*TODO*/
}
-void
+static void
loop_fork (EV_P)
{
- /*TODO*/
#if EV_USE_EPOLL
if (method == EVMETHOD_EPOLL ) epoll_fork (EV_A);
#endif
#if EV_USE_KQUEUE
if (method == EVMETHOD_KQUEUE) kqueue_fork (EV_A);
#endif
+
+ if (ev_is_active (&sigev))
+ {
+ /* default loop */
+
+ 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);
+ }
+
+ postfork = 0;
}
#if EV_MULTIPLICITY
@@ -771,7 +792,7 @@ ev_loop_destroy (EV_P)
void
ev_loop_fork (EV_P)
{
- loop_fork (EV_A);
+ postfork = 1;
}
#endif
@@ -804,8 +825,6 @@ ev_default_loop (int methods)
if (ev_method (EV_A))
{
- ev_watcher_init (&sigev, sigcb);
- ev_set_priority (&sigev, EV_MAXPRI);
siginit (EV_A);
#ifndef WIN32
@@ -848,15 +867,8 @@ ev_default_fork (void)
struct ev_loop *loop = default_loop;
#endif
- loop_fork (EV_A);
-
- ev_io_stop (EV_A_ &sigev);
- close (sigpipe [0]);
- close (sigpipe [1]);
- pipe (sigpipe);
-
- ev_ref (EV_A); /* signal watcher */
- siginit (EV_A);
+ if (method)
+ postfork = 1;
}
/*****************************************************************************/
@@ -1044,6 +1056,10 @@ ev_loop (EV_P_ int flags)
call_pending (EV_A);
}
+ /* we might have forked, so reify kernel state if necessary */
+ if (expect_false (postfork))
+ loop_fork (EV_A);
+
/* update fd-related kernel structures */
fd_reify (EV_A);
diff --git a/ev.h b/ev.h
index 08b5963..83cda6f 100644
--- a/ev.h
+++ b/ev.h
@@ -241,7 +241,7 @@ void ev_set_allocator (void *(*cb)(void *ptr, long size));
* retryable syscall error
* (such as failed select, poll, epoll_wait)
*/
-void ev_set_syserr_cb (void (*cb)(void));
+void ev_set_syserr_cb (void (*cb)(const char *msg));
# if EV_MULTIPLICITY
/* the default loop is the only one that handles signals and child watchers */
diff --git a/ev_epoll.c b/ev_epoll.c
index 6bb41bc..2040103 100644
--- a/ev_epoll.c
+++ b/ev_epoll.c
@@ -57,7 +57,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
if (eventcnt < 0)
{
if (errno != EINTR)
- syserr ();
+ syserr ("(libev) epoll_wait");
return;
}
@@ -110,7 +110,16 @@ epoll_destroy (EV_P)
static void
epoll_fork (EV_P)
{
- epoll_fd = epoll_create (256);
+ for (;;)
+ {
+ epoll_fd = epoll_create (256);
+
+ if (epoll_fd >= 0)
+ break;
+
+ syserr ("(libev) epoll_create");
+ }
+
fcntl (epoll_fd, F_SETFD, FD_CLOEXEC);
fd_rearm_all (EV_A);
diff --git a/ev_kqueue.c b/ev_kqueue.c
index 4fefcee..07d16e4 100644
--- a/ev_kqueue.c
+++ b/ev_kqueue.c
@@ -87,7 +87,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
if (res < 0)
{
if (errno != EINTR)
- syserr ();
+ syserr ("(libev) kevent");
return;
}
@@ -185,7 +185,16 @@ kqueue_destroy (EV_P)
static void
kqueue_fork (EV_P)
{
- kqueue_fd = kqueue ();
+ for (;;)
+ {
+ kqueue_fd = kqueue ();
+
+ if (kqueue_fd >= 0)
+ break;
+
+ syserr ("(libev) kqueue");
+ }
+
fcntl (kqueue_fd, F_SETFD, FD_CLOEXEC);
/* re-register interest in fds */
diff --git a/ev_poll.c b/ev_poll.c
index e809ddd..1ce41c6 100644
--- a/ev_poll.c
+++ b/ev_poll.c
@@ -85,7 +85,7 @@ poll_poll (EV_P_ ev_tstamp timeout)
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
- syserr ();
+ syserr ("(libev) poll");
return;
}
diff --git a/ev_select.c b/ev_select.c
index 5f75e37..e3e79ca 100644
--- a/ev_select.c
+++ b/ev_select.c
@@ -96,7 +96,7 @@ select_poll (EV_P_ ev_tstamp timeout)
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
- syserr ();
+ syserr ("(libev) select");
return;
}
diff --git a/ev_vars.h b/ev_vars.h
index 98029ed..c506944 100644
--- a/ev_vars.h
+++ b/ev_vars.h
@@ -10,6 +10,7 @@ VARx(ev_tstamp, method_fudge) /* assumed typical timer resolution */
VAR (method_modify, void (*method_modify)(EV_P_ int fd, int oev, int nev))
VAR (method_poll , void (*method_poll)(EV_P_ ev_tstamp timeout))
+VARx(int, postfork) /* true if we need to recreate kernel state after fork */
VARx(int, activecnt) /* number of active events */
#if EV_USE_SELECT || EV_GENWRAP