From 29fdb3471ba993a4d129278129ec04e720890063 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Sat, 26 Oct 2013 01:06:12 +0400 Subject: [PATCH] unix: update events from pevents between polls Watchers could be stopped between two `kevent()`/`epoll_wait()` calls (which may happen in the same loop in `uv__io_poll()`), in such cases `watcher->events` could be stale and won't be updated to `watcher->pevents`. Try to use and rely on `watcher->pevents` instead of blindly expecting `watcher->events` to be always correct. --- src/unix/kqueue.c | 4 ++-- src/unix/linux-core.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/unix/kqueue.c b/src/unix/kqueue.c index 378903a6..d99d6e1b 100644 --- a/src/unix/kqueue.c +++ b/src/unix/kqueue.c @@ -191,7 +191,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { revents = 0; if (ev->filter == EVFILT_READ) { - if (w->events & UV__POLLIN) { + if (w->pevents & UV__POLLIN) { revents |= UV__POLLIN; w->rcount = ev->data; } else { @@ -205,7 +205,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } if (ev->filter == EVFILT_WRITE) { - if (w->events & UV__POLLOUT) { + if (w->pevents & UV__POLLOUT) { revents |= UV__POLLOUT; w->wcount = ev->data; } else { diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c index e4c34a18..cb6df789 100644 --- a/src/unix/linux-core.c +++ b/src/unix/linux-core.c @@ -105,6 +105,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { uv__io_t* w; uint64_t base; uint64_t diff; + unsigned int masked_events; int nevents; int count; int nfds; @@ -208,7 +209,15 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { continue; } - w->cb(loop, w, pe->events); + /* + * Give users only events they're interested in. Prevents spurious + * callbacks when previous callback invocation in this loop has stopped + * the current watcher. Also, filters out events that users has not + * requested us to watch. + */ + masked_events = pe->events & w->pevents; + if (masked_events != 0) + w->cb(loop, w, masked_events); nevents++; }