summary refs log tree commit diff
path: root/evloop
diff options
context:
space:
mode:
authorRichard Nyberg <rnyberg@murmeldjur.se>2009-02-17 18:35:24 +0100
committerRichard Nyberg <rnyberg@murmeldjur.se>2009-02-17 18:35:24 +0100
commitc94ed423cf2388480c4766c019b6853280ffcbbd (patch)
tree3f11ab4af4bf1bfc8dc5e9f8b8987112c8ad767a /evloop
parent86500486e77860b7418e0bf2d8fa312db2484037 (diff)
downloadbtpd-c94ed423cf2388480c4766c019b6853280ffcbbd.tar.gz
btpd-c94ed423cf2388480c4766c019b6853280ffcbbd.zip
Fix possible crash with kqueue.
With kqueue, a fdev may be in two active kevents.
Diffstat (limited to 'evloop')
-rw-r--r--evloop/evloop.h5
-rw-r--r--evloop/kqueue.c48
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);
 }
 
@@ -100,23 +103,38 @@ evloop(void)
         }
         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;
+            }
         }
     }
 }