summaryrefslogtreecommitdiff
path: root/ev_epoll.c
diff options
context:
space:
mode:
Diffstat (limited to 'ev_epoll.c')
-rw-r--r--ev_epoll.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/ev_epoll.c b/ev_epoll.c
index 4c36cfa..f1e16ab 100644
--- a/ev_epoll.c
+++ b/ev_epoll.c
@@ -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;