From c94ed423cf2388480c4766c019b6853280ffcbbd Mon Sep 17 00:00:00 2001 From: Richard Nyberg Date: Tue, 17 Feb 2009 18:35:24 +0100 Subject: [PATCH] Fix possible crash with kqueue. With kqueue, a fdev may be in two active kevents. --- evloop/evloop.h | 5 +++++ evloop/kqueue.c | 48 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/evloop/evloop.h b/evloop/evloop.h index 44f8803..28b4572 100644 --- a/evloop/evloop.h +++ b/evloop/evloop.h @@ -19,7 +19,12 @@ struct fdev { void *arg; int fd; uint16_t flags; +#ifdef EVLOOP_EPOLL int16_t index; +#else + int16_t rdidx; + int16_t wridx; +#endif }; #elif defined(EVLOOP_POLL) diff --git a/evloop/kqueue.c b/evloop/kqueue.c index 649e838..6cd971e 100644 --- a/evloop/kqueue.c +++ b/evloop/kqueue.c @@ -29,7 +29,8 @@ fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb, void *arg) ev->cb = cb; ev->arg = arg; ev->flags = 0; - ev->index = -1; + ev->rdidx = -1; + ev->wridx = -1; return fdev_enable(ev, flags); } @@ -78,8 +79,10 @@ fdev_disable(struct fdev *ev, uint16_t flags) int fdev_del(struct fdev *ev) { - if (ev->index >= 0) - m_valid[ev->index] = 0; + if (ev->rdidx >= 0) + m_valid[ev->rdidx] = 0; + if (ev->wridx >= 0) + m_valid[ev->wridx] = 0; return fdev_disable(ev, EV_READ|EV_WRITE); } @@ -99,24 +102,39 @@ evloop(void) return -1; } memset(m_valid, 1, nev); - for (i = 0; i < nev; i++) { - struct fdev *ev = (struct fdev *)m_evs[i].udata; - ev->index = i; - } for (i = 0; i < nev; i++) { if (m_evs[i].flags & EV_ERROR) { errno = m_evs[i].data; return -1; } struct fdev *ev = (struct fdev *)m_evs[i].udata; - if (m_valid[i] && ev->flags & EV_READ && - m_evs[i].filter == EVFILT_READ) - ev->cb(ev->fd, EV_READ, ev->arg); - if (m_valid[i] && ev->flags & EV_WRITE && - m_evs[i].filter == EVFILT_WRITE) - ev->cb(ev->fd, EV_WRITE, ev->arg); - if (m_valid[i]) - ev->index = -1; + switch (m_evs[i].filter) { + case EVFILT_READ: + ev->rdidx = i; + break; + case EVFILT_WRITE: + ev->wridx = i; + break; + } + } + for (i = 0; i < nev; i++) { + if (!m_valid[i]) + continue; + struct fdev *ev = (struct fdev *)m_evs[i].udata; + switch (m_evs[i].filter) { + case EVFILT_READ: + if (ev->flags & EV_READ) + ev->cb(ev->fd, EV_READ, ev->arg); + if (m_valid[i]) + ev->rdidx = -1; + break; + case EVFILT_WRITE: + if (ev->flags & EV_WRITE) + ev->cb(ev->fd, EV_WRITE, ev->arg); + if (m_valid[i]) + ev->wridx = -1; + break; + } } } }