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.
This commit is contained in:
Fedor Indutny 2013-10-26 01:06:12 +04:00
parent 08e0e63f3a
commit 29fdb3471b
2 changed files with 12 additions and 3 deletions

View File

@ -191,7 +191,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
revents = 0; revents = 0;
if (ev->filter == EVFILT_READ) { if (ev->filter == EVFILT_READ) {
if (w->events & UV__POLLIN) { if (w->pevents & UV__POLLIN) {
revents |= UV__POLLIN; revents |= UV__POLLIN;
w->rcount = ev->data; w->rcount = ev->data;
} else { } else {
@ -205,7 +205,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
} }
if (ev->filter == EVFILT_WRITE) { if (ev->filter == EVFILT_WRITE) {
if (w->events & UV__POLLOUT) { if (w->pevents & UV__POLLOUT) {
revents |= UV__POLLOUT; revents |= UV__POLLOUT;
w->wcount = ev->data; w->wcount = ev->data;
} else { } else {

View File

@ -105,6 +105,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
uv__io_t* w; uv__io_t* w;
uint64_t base; uint64_t base;
uint64_t diff; uint64_t diff;
unsigned int masked_events;
int nevents; int nevents;
int count; int count;
int nfds; int nfds;
@ -208,7 +209,15 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
continue; 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++; nevents++;
} }