diff options
| author | root <root> | 2007-11-06 00:52:32 +0000 | 
|---|---|---|
| committer | root <root> | 2007-11-06 00:52:32 +0000 | 
| commit | 499c7e995433fedd0a2333ec6d9bc3768e6224f4 (patch) | |
| tree | 63804fd270e45b25889a1d3a380e3912ada25a4b | |
| parent | deff62d26ff4c1324816c04c0c6db1e4db435870 (diff) | |
better fork
| -rw-r--r-- | ev.c | 60 | ||||
| -rw-r--r-- | ev.h | 2 | ||||
| -rw-r--r-- | ev_epoll.c | 13 | ||||
| -rw-r--r-- | ev_kqueue.c | 13 | ||||
| -rw-r--r-- | ev_poll.c | 2 | ||||
| -rw-r--r-- | ev_select.c | 2 | ||||
| -rw-r--r-- | ev_vars.h | 1 | 
7 files changed, 64 insertions, 29 deletions
@@ -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); @@ -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 */ @@ -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 */ @@ -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;      } @@ -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  | 
