]> git.llucax.com Git - software/libev.git/blobdiff - ev.c
*** empty log message ***
[software/libev.git] / ev.c
diff --git a/ev.c b/ev.c
index e94ede40e7a96f6108a8688d29091e26831ab67c..6c2f3977d815a785bbdc78b5acd24b8f410b9f10 100644 (file)
--- a/ev.c
+++ b/ev.c
@@ -44,7 +44,9 @@
 #include <assert.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/wait.h>
+#ifndef WIN32
+# include <sys/wait.h>
+#endif
 #include <sys/time.h>
 #include <time.h>
 
 # define EV_USE_SELECT 1
 #endif
 
+#ifndef EV_USE_POLL
+# define EV_USE_POLL 0 /* poll is usually slower than select, and not as well tested */
+#endif
+
 #ifndef EV_USE_EPOLL
 # define EV_USE_EPOLL 0
 #endif
 
+#ifndef EV_USE_KQUEUE
+# define EV_USE_KQUEUE 0
+#endif
+
 #ifndef EV_USE_REALTIME
 # define EV_USE_REALTIME 1
 #endif
 #define expect_false(expr) expect ((expr) != 0, 0)
 #define expect_true(expr)  expect ((expr) != 0, 1)
 
+#define NUMPRI    (EV_MAXPRI - EV_MINPRI + 1)
+#define ABSPRI(w) ((w)->priority - EV_MINPRI)
+
 typedef struct ev_watcher *W;
 typedef struct ev_watcher_list *WL;
 typedef struct ev_watcher_time *WT;
@@ -191,22 +204,22 @@ typedef struct
   int events;
 } ANPENDING;
 
-static ANPENDING *pendings;
-static int pendingmax, pendingcnt;
+static ANPENDING *pendings [NUMPRI];
+static int pendingmax [NUMPRI], pendingcnt [NUMPRI];
 
 static void
 event (W w, int events)
 {
   if (w->pending)
     {
-      pendings [w->pending - 1].events |= events;
+      pendings [ABSPRI (w)][w->pending - 1].events |= events;
       return;
     }
 
-  w->pending = ++pendingcnt;
-  array_needsize (pendings, pendingmax, pendingcnt, );
-  pendings [pendingcnt - 1].w      = w;
-  pendings [pendingcnt - 1].events = events;
+  w->pending = ++pendingcnt [ABSPRI (w)];
+  array_needsize (pendings [ABSPRI (w)], pendingmax [ABSPRI (w)], pendingcnt [ABSPRI (w)], );
+  pendings [ABSPRI (w)][w->pending - 1].w      = w;
+  pendings [ABSPRI (w)][w->pending - 1].events = events;
 }
 
 static void
@@ -279,20 +292,44 @@ fd_change (int fd)
   fdchanges [fdchangecnt - 1] = fd;
 }
 
+static void
+fd_kill (int fd)
+{
+  struct ev_io *w;
+
+  printf ("killing fd %d\n", fd);//D
+  while ((w = anfds [fd].head))
+    {
+      ev_io_stop (w);
+      event ((W)w, EV_ERROR | EV_READ | EV_WRITE);
+    }
+}
+
 /* called on EBADF to verify fds */
 static void
-fd_recheck (void)
+fd_ebadf (void)
 {
   int fd;
 
   for (fd = 0; fd < anfdmax; ++fd)
     if (anfds [fd].events)
       if (fcntl (fd, F_GETFD) == -1 && errno == EBADF)
-        while (anfds [fd].head)
-          {
-            ev_io_stop (anfds [fd].head);
-            event ((W)anfds [fd].head, EV_ERROR | EV_READ | EV_WRITE);
-          }
+        fd_kill (fd);
+}
+
+/* called on ENOMEM in select/poll to kill some fds and retry */
+static void
+fd_enomem (void)
+{
+  int fd = anfdmax;
+
+  while (fd--)
+    if (anfds [fd].events)
+      {
+        close (fd);
+        fd_kill (fd);
+        return;
+      }
 }
 
 /*****************************************************************************/
@@ -405,12 +442,14 @@ sigcb (struct ev_io *iow, int revents)
 static void
 siginit (void)
 {
+#ifndef WIN32
   fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC);
   fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC);
 
   /* rather than sort out wether we really need nb, set it */
   fcntl (sigpipe [0], F_SETFL, O_NONBLOCK);
   fcntl (sigpipe [1], F_SETFL, O_NONBLOCK);
+#endif
 
   ev_io_set (&sigev, sigpipe [0], EV_READ);
   ev_io_start (&sigev);
@@ -432,6 +471,8 @@ static int checkmax, checkcnt;
 static struct ev_child *childs [PID_HASHSIZE];
 static struct ev_signal childev;
 
+#ifndef WIN32
+
 #ifndef WCONTINUED
 # define WCONTINUED 0
 #endif
@@ -446,16 +487,25 @@ childcb (struct ev_signal *sw, int revents)
     for (w = childs [pid & (PID_HASHSIZE - 1)]; w; w = w->next)
       if (w->pid == pid || !w->pid)
         {
-          w->status = status;
+          w->rpid    = pid;
+          w->rstatus = status;
           event ((W)w, EV_CHILD);
         }
 }
 
+#endif
+
 /*****************************************************************************/
 
+#if EV_USE_KQUEUE
+# include "ev_kqueue.c"
+#endif
 #if EV_USE_EPOLL
 # include "ev_epoll.c"
 #endif
+#if EV_USE_POLL
+# include "ev_poll.c"
+#endif
 #if EV_USE_SELECT
 # include "ev_select.c"
 #endif
@@ -472,7 +522,15 @@ ev_version_minor (void)
   return EV_VERSION_MINOR;
 }
 
-int ev_init (int flags)
+/* return true if we are running with elevated privileges and ignore env variables */
+static int
+enable_secure ()
+{
+  return getuid () != geteuid ()
+      || getgid () != getegid ();
+}
+
+int ev_init (int methods)
 {
   if (!ev_method)
     {
@@ -492,12 +550,24 @@ int ev_init (int flags)
       if (pipe (sigpipe))
         return 0;
 
-      ev_method = EVMETHOD_NONE;
+      if (methods == EVMETHOD_AUTO)
+          if (!enable_secure () && getenv ("LIBEV_METHODS"))
+            methods = atoi (getenv ("LIBEV_METHODS"));
+          else
+            methods = EVMETHOD_ANY;
+
+      ev_method = 0;
+#if EV_USE_KQUEUE
+      if (!ev_method && (methods & EVMETHOD_KQUEUE)) kqueue_init (methods);
+#endif
 #if EV_USE_EPOLL
-      if (ev_method == EVMETHOD_NONE) epoll_init (flags);
+      if (!ev_method && (methods & EVMETHOD_EPOLL )) epoll_init  (methods);
+#endif
+#if EV_USE_POLL
+      if (!ev_method && (methods & EVMETHOD_POLL  )) poll_init   (methods);
 #endif
 #if EV_USE_SELECT
-      if (ev_method == EVMETHOD_NONE) select_init (flags);
+      if (!ev_method && (methods & EVMETHOD_SELECT)) select_init (methods);
 #endif
 
       if (ev_method)
@@ -505,8 +575,10 @@ int ev_init (int flags)
           ev_watcher_init (&sigev, sigcb);
           siginit ();
 
+#ifndef WIN32
           ev_signal_init (&childev, childcb, SIGCHLD);
           ev_signal_start (&childev);
+#endif
         }
     }
 
@@ -547,16 +619,19 @@ ev_fork_child (void)
 static void
 call_pending (void)
 {
-  while (pendingcnt)
-    {
-      ANPENDING *p = pendings + --pendingcnt;
+  int pri;
 
-      if (p->w)
-        {
-          p->w->pending = 0;
-          p->w->cb (p->w, p->events);
-        }
-    }
+  for (pri = NUMPRI; pri--; )
+    while (pendingcnt [pri])
+      {
+        ANPENDING *p = pendings [pri] + --pendingcnt [pri];
+
+        if (p->w)
+          {
+            p->w->pending = 0;
+            p->w->cb (p->w, p->events);
+          }
+      }
 }
 
 static void
@@ -798,7 +873,7 @@ ev_clear_pending (W w)
 {
   if (w->pending)
     {
-      pendings [w->pending - 1].w = 0;
+      pendings [ABSPRI (w)][w->pending - 1].w = 0;
       w->pending = 0;
     }
 }
@@ -806,6 +881,9 @@ ev_clear_pending (W w)
 static void
 ev_start (W w, int active)
 {
+  if (w->priority < EV_MINPRI) w->priority = EV_MINPRI;
+  if (w->priority > EV_MAXPRI) w->priority = EV_MAXPRI;
+
   w->active = active;
 }