diff options
| -rw-r--r-- | Changes | 3 | ||||
| -rw-r--r-- | ev.c | 1 | ||||
| -rw-r--r-- | ev_epoll.c | 34 | 
3 files changed, 21 insertions, 17 deletions
| @@ -6,7 +6,8 @@ WISH? monotonic clocks times/GetTickCount for coarse corrections?            backend by assuming the kernel event mask hasn't changed if            ADD fails with EEXIST.          - work around spurious event notification bugs in epoll by using -          an 8-bit generation counter. +          an 8-bit generation counter. recreate kernel state if we receive +          spurious notifications or unwanted events.          - use memset to initialise most arrays now and do away with the            init functions.          - expand time-out strategies into a "Be smart about timeouts" section. @@ -808,6 +808,7 @@ fd_rearm_all (EV_P)      if (anfds [fd].events)        {          anfds [fd].events = 0; +        anfds [fd].emask  = 0;          fd_change (EV_A_ fd, EV_IOFDSET | 1);        }  } @@ -52,19 +52,13 @@   *   * lots of "weird code" and complication handling in this file is due   * to these design problems with epoll, as we try very hard to avoid - * epoll_ctl syscalls for common usage patterns. + * epoll_ctl syscalls for common usage patterns and handle the breakage + * ensuing from receiving events for closed and otherwise long gone + * file descriptors.   */  #include <sys/epoll.h> -void inline_size -unsigned_char_init (unsigned char *base, int count) -{ -  /* memset might be overkill */ -  while (count--) -    *base++ = 0; -} -  static void  epoll_modify (EV_P_ int fd, int oev, int nev)  { @@ -138,14 +132,18 @@ epoll_poll (EV_P_ ev_tstamp timeout)      {        struct epoll_event *ev = epoll_events + i; -      int fd   = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */ +      int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */ +      int want = anfds [fd].events;        int got  = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)                 | (ev->events & (EPOLLIN  | EPOLLERR | EPOLLHUP) ? EV_READ  : 0); -      int want = anfds [fd].events; -      if (anfds [fd].egen != (unsigned char)(ev->data.u64 >> 32)) -        /*fprintf (stderr, "spurious notification fd %d, %d vs %d\n", fd, (int)(ev->data.u64 >> 32), anfds [fd].egen);*/ -        continue; +      /* check for spurious notification */ +      if (expect_false (anfds [fd].egen != (unsigned char)(ev->data.u64 >> 32))) +        { +          /* recreate kernel state */ +          postfork = 1; +          continue; +        }        if (expect_false (got & ~want))          { @@ -156,7 +154,11 @@ epoll_poll (EV_P_ ev_tstamp timeout)            ev->events = (want & EV_READ  ? EPOLLIN  : 0)                       | (want & EV_WRITE ? EPOLLOUT : 0); -          epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev); +          if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)) +            { +              postfork = 1; /* an error occured, recreate kernel state */ +              continue; +            }          }        fd_event (EV_A_ fd, got); @@ -185,7 +187,7 @@ epoll_init (EV_P_ int flags)    backend_modify = epoll_modify;    backend_poll   = epoll_poll; -  epoll_eventmax = 64; /* intiial number of events receivable per poll */ +  epoll_eventmax = 64; /* initial number of events receivable per poll */    epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);    return EVBACKEND_EPOLL; | 
