]> git.llucax.com Git - software/libev.git/commitdiff
better error handling
authorroot <root>
Tue, 6 Nov 2007 00:10:04 +0000 (00:10 +0000)
committerroot <root>
Tue, 6 Nov 2007 00:10:04 +0000 (00:10 +0000)
ev.c
ev.h
ev_epoll.c
ev_kqueue.c
ev_poll.c
ev_select.c

diff --git a/ev.c b/ev.c
index 7c312af961b30fbcc3e28d48e32882bdb515afd2..c12037c988f1679ed37dd8e73bc8c0d8aea956d9 100644 (file)
--- a/ev.c
+++ b/ev.c
@@ -155,6 +155,51 @@ volatile double SIGFPE_REQ = 0.0f;
 
 /*****************************************************************************/
 
+static void (*syserr_cb)(void);
+
+void ev_set_syserr_cb (void (*cb)(void))
+{
+  syserr_cb = cb;
+}
+
+static void
+syserr (void)
+{
+  if (syserr_cb)
+    syserr_cb ();
+  else
+    {
+      perror ("libev");
+      abort ();
+    }
+}
+
+static void *(*alloc)(void *ptr, long size);
+
+void ev_set_allocator (void *(*cb)(void *ptr, long size))
+{
+  alloc = cb;
+}
+
+static void *
+ev_realloc (void *ptr, long size)
+{
+  ptr = alloc ? alloc (ptr, size) : realloc (ptr, size);
+
+  if (!ptr && size)
+    {
+      fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
+      abort ();
+    }
+
+  return ptr;
+}
+
+#define ev_malloc(size) ev_realloc (0, (size))
+#define ev_free(ptr)    ev_realloc ((ptr), 0)
+
+/*****************************************************************************/
+
 typedef struct
 {
   WL head;
@@ -225,31 +270,31 @@ ev_now (EV_P)
 
 #define array_roundsize(base,n) ((n) | 4 & ~3)
 
-#define array_needsize(base,cur,cnt,init)              \
-  if (expect_false ((cnt) > cur))                      \
-    {                                                  \
-      int newcnt = cur;                                        \
-      do                                               \
-        {                                              \
-          newcnt = array_roundsize (base, newcnt << 1);        \
-        }                                              \
-      while ((cnt) > newcnt);                          \
-                                                       \
-      base = realloc (base, sizeof (*base) * (newcnt));        \
-      init (base + cur, newcnt - cur);                 \
-      cur = newcnt;                                    \
+#define array_needsize(base,cur,cnt,init)                      \
+  if (expect_false ((cnt) > cur))                              \
+    {                                                          \
+      int newcnt = cur;                                                \
+      do                                                       \
+        {                                                      \
+          newcnt = array_roundsize (base, newcnt << 1);                \
+        }                                                      \
+      while ((cnt) > newcnt);                                  \
+                                                               \
+      base = ev_realloc (base, sizeof (*base) * (newcnt));     \
+      init (base + cur, newcnt - cur);                         \
+      cur = newcnt;                                            \
     }
 
 #define array_slim(stem)                                       \
   if (stem ## max < array_roundsize (stem ## cnt >> 2))                \
     {                                                          \
       stem ## max = array_roundsize (stem ## cnt >> 1);                \
-      base = realloc (base, sizeof (*base) * (stem ## max));   \
+      base = ev_realloc (base, sizeof (*base) * (stem ## max));        \
       fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\
     }
 
 #define array_free(stem, idx) \
-  free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
+  ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
 
 /*****************************************************************************/
 
@@ -704,7 +749,9 @@ loop_fork (EV_P)
 struct ev_loop *
 ev_loop_new (int methods)
 {
-  struct ev_loop *loop = (struct ev_loop *)calloc (1, sizeof (struct ev_loop));
+  struct ev_loop *loop = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
+
+  memset (loop, 0, sizeof (struct ev_loop));
 
   loop_init (EV_A_ methods);
 
@@ -718,7 +765,7 @@ void
 ev_loop_destroy (EV_P)
 {
   loop_destroy (EV_A);
-  free (loop);
+  ev_free (loop);
 }
 
 void
@@ -1397,7 +1444,7 @@ once_cb (EV_P_ struct ev_once *once, int revents)
 
   ev_io_stop (EV_A_ &once->io);
   ev_timer_stop (EV_A_ &once->to);
-  free (once);
+  ev_free (once);
 
   cb (revents, arg);
 }
@@ -1417,7 +1464,7 @@ once_cb_to (EV_P_ struct ev_timer *w, int revents)
 void
 ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
 {
-  struct ev_once *once = malloc (sizeof (struct ev_once));
+  struct ev_once *once = ev_malloc (sizeof (struct ev_once));
 
   if (!once)
     cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMEOUT, arg);
diff --git a/ev.h b/ev.h
index 1933285bbb28924d72ee793f63d19fb43ac2ac81..08b5963e631abfae28e454b8aa2979d2e705fa38 100644 (file)
--- a/ev.h
+++ b/ev.h
@@ -229,6 +229,20 @@ int ev_version_minor (void);
 
 ev_tstamp ev_time (void);
 
+/* Sets the allocation function to use, works like realloc.
+ * It is used to allocate and free memory.
+ * If it returns zero when memory needs to be allocated, the library might abort
+ * or take some potentially destructive action.
+ * The default is your system realloc function.
+ */
+void ev_set_allocator (void *(*cb)(void *ptr, long size));
+
+/* set the callback function to call on a
+ * retryable syscall error
+ * (such as failed select, poll, epoll_wait)
+ */
+void ev_set_syserr_cb (void (*cb)(void));
+
 # if EV_MULTIPLICITY
 /* the default loop is the only one that handles signals and child watchers */
 /* you can call this as often as you like */
index 4689f8d3b3baf8ad09992f1b8ec1f9b88d8f39e8..6bb41bccc2004886e213baa6361fe6285d318b32 100644 (file)
@@ -51,11 +51,16 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
 static void
 epoll_poll (EV_P_ ev_tstamp timeout)
 {
-  int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.));
   int i;
+  int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.));
 
   if (eventcnt < 0)
-    return;
+    {
+      if (errno != EINTR)
+        syserr ();
+
+      return;
+    }
 
   for (i = 0; i < eventcnt; ++i)
     fd_event (
@@ -68,9 +73,9 @@ epoll_poll (EV_P_ ev_tstamp timeout)
   /* if the receive array was full, increase its size */
   if (expect_false (eventcnt == epoll_eventmax))
     {
-      free (epoll_events);
+      ev_free (epoll_events);
       epoll_eventmax = array_roundsize (epoll_events, epoll_eventmax << 1);
-      epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax);
+      epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
     }
 }
 
@@ -89,7 +94,7 @@ epoll_init (EV_P_ int flags)
   method_poll   = epoll_poll;
 
   epoll_eventmax = 64; /* intiial number of events receivable per poll */
-  epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax);
+  epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
 
   return EVMETHOD_EPOLL;
 }
@@ -99,7 +104,7 @@ epoll_destroy (EV_P)
 {
   close (epoll_fd);
 
-  free (epoll_events);
+  ev_free (epoll_events);
 }
 
 static void
index 24c3015b308ee781a5775623de389ef570564b32..4fefceeec6eb9185c8194de6b2beeacf5b49285d 100644 (file)
@@ -85,7 +85,12 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
   kqueue_changecnt = 0;
 
   if (res < 0)
-    return;
+    { 
+      if (errno != EINTR)
+        syserr ();
+
+      return;
+    } 
 
   for (i = 0; i < res; ++i)
     {
@@ -118,9 +123,9 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
 
   if (expect_false (res == kqueue_eventmax))
     {
-      free (kqueue_events);
+      ev_free (kqueue_events);
       kqueue_eventmax = array_roundsize (kqueue_events, kqueue_eventmax << 1);
-      kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax);
+      kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
     }
 }
 
@@ -159,7 +164,7 @@ kqueue_init (EV_P_ int flags)
   method_poll   = kqueue_poll;
 
   kqueue_eventmax = 64; /* intiial number of events receivable per poll */
-  kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax);
+  kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
 
   kqueue_changes   = 0;
   kqueue_changemax = 0;
@@ -173,8 +178,8 @@ kqueue_destroy (EV_P)
 {
   close (kqueue_fd);
 
-  free (kqueue_events);
-  free (kqueue_changes);
+  ev_free (kqueue_events);
+  ev_free (kqueue_changes);
 }
 
 static void
index b58ce8232a862c0d8219e8050be58e302bd50663..e809dddeb3b3504cc447ce6baad066cac2a2bb0f 100644 (file)
--- a/ev_poll.c
+++ b/ev_poll.c
@@ -75,27 +75,28 @@ poll_modify (EV_P_ int fd, int oev, int nev)
 static void
 poll_poll (EV_P_ ev_tstamp timeout)
 {
+  int i;
   int res = poll (polls, pollcnt, ceil (timeout * 1000.));
 
-  if (res > 0)
-    {
-      int i;
-
-      for (i = 0; i < pollcnt; ++i)
-        fd_event (
-          EV_A_
-          polls [i].fd,
-          (polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
-          | (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
-        );
-    }
-  else if (res < 0)
+  if (res < 0)
     {
       if (errno == EBADF)
         fd_ebadf (EV_A);
-      else if (errno == ENOMEM)
+      else if (errno == ENOMEM && !syserr_cb)
         fd_enomem (EV_A);
+      else if (errno != EINTR)
+        syserr ();
+
+      return;
     }
+
+  for (i = 0; i < pollcnt; ++i)
+    fd_event (
+      EV_A_
+      polls [i].fd,
+      (polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
+      | (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
+    );
 }
 
 static int
@@ -114,6 +115,6 @@ poll_init (EV_P_ int flags)
 static void
 poll_destroy (EV_P)
 {
-  free (pollidxs);
-  free (polls);
+  ev_free (pollidxs);
+  ev_free (polls);
 }
index 9f81e555799180dcca46f4274458be5976942b91..5f75e376504b268069d858db79319f948382735d 100644 (file)
@@ -55,10 +55,10 @@ select_modify (EV_P_ int fd, int oev, int nev)
     {
       int new_max = (fd >> 5) + 1;
 
-      vec_ri = (unsigned char *)realloc (vec_ri, new_max * 4);
-      vec_ro = (unsigned char *)realloc (vec_ro, new_max * 4); /* could free/malloc */
-      vec_wi = (unsigned char *)realloc (vec_wi, new_max * 4);
-      vec_wo = (unsigned char *)realloc (vec_wo, new_max * 4); /* could free/malloc */
+      vec_ri = (unsigned char *)ev_realloc (vec_ri, new_max * 4);
+      vec_ro = (unsigned char *)ev_realloc (vec_ro, new_max * 4); /* could free/malloc */
+      vec_wi = (unsigned char *)ev_realloc (vec_wi, new_max * 4);
+      vec_wo = (unsigned char *)ev_realloc (vec_wo, new_max * 4); /* could free/malloc */
 
       for (; vec_max < new_max; ++vec_max)
         ((uint32_t *)vec_ri)[vec_max] =
@@ -77,6 +77,7 @@ select_modify (EV_P_ int fd, int oev, int nev)
 static void
 select_poll (EV_P_ ev_tstamp timeout)
 {
+  int word, offs;
   struct timeval tv;
   int res;
 
@@ -88,39 +89,39 @@ select_poll (EV_P_ ev_tstamp timeout)
 
   res = select (vec_max * 32, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
 
-  if (res > 0)
-    {
-      int word, offs;
-
-      for (word = vec_max; word--; )
-        {
-          if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word])
-            for (offs = 4; offs--; )
-              {
-                int idx = word * 4 + offs;
-                unsigned char byte_r = vec_ro [idx];
-                unsigned char byte_w = vec_wo [idx];
-                int bit;
-
-                if (byte_r | byte_w)
-                  for (bit = 8; bit--; )
-                    {
-                      int events = 0;
-                      events |= byte_r & (1 << bit) ? EV_READ  : 0;
-                      events |= byte_w & (1 << bit) ? EV_WRITE : 0;
-
-                      if (events)
-                        fd_event (EV_A_ idx * 8 + bit, events);
-                    }
-              }
-        }
-    }
-  else if (res < 0)
+  if (res < 0)
     {
       if (errno == EBADF)
         fd_ebadf (EV_A);
-      else if (errno == ENOMEM)
+      else if (errno == ENOMEM && !syserr_cb)
         fd_enomem (EV_A);
+      else if (errno != EINTR)
+        syserr ();
+
+      return;
+    }
+
+  for (word = vec_max; word--; )
+    {
+      if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word])
+        for (offs = 4; offs--; )
+          {
+            int idx = word * 4 + offs;
+            unsigned char byte_r = vec_ro [idx];
+            unsigned char byte_w = vec_wo [idx];
+            int bit;
+
+            if (byte_r | byte_w)
+              for (bit = 8; bit--; )
+                {
+                  int events = 0;
+                  events |= byte_r & (1 << bit) ? EV_READ  : 0;
+                  events |= byte_w & (1 << bit) ? EV_WRITE : 0;
+
+                  if (events)
+                    fd_event (EV_A_ idx * 8 + bit, events);
+                }
+          }
     }
 }
 
@@ -143,10 +144,10 @@ select_init (EV_P_ int flags)
 static void
 select_destroy (EV_P)
 {
-  free (vec_ri);
-  free (vec_ro);
-  free (vec_wi);
-  free (vec_wo);
+  ev_free (vec_ri);
+  ev_free (vec_ro);
+  ev_free (vec_wi);
+  ev_free (vec_wo);
 }