-
Notifications
You must be signed in to change notification settings - Fork 653
unix: fix reopened fd bug #971
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -595,20 +595,33 @@ static unsigned int next_power_of_two(unsigned int val) { | |
|
||
static void maybe_resize(uv_loop_t* loop, unsigned int len) { | ||
uv__io_t** watchers; | ||
void* fake_watcher_list; | ||
void* fake_watcher_count; | ||
unsigned int nwatchers; | ||
unsigned int i; | ||
|
||
if (len <= loop->nwatchers) | ||
return; | ||
|
||
nwatchers = next_power_of_two(len); | ||
watchers = realloc(loop->watchers, nwatchers * sizeof(loop->watchers[0])); | ||
nwatchers = next_power_of_two(len + 2) - 2; | ||
watchers = realloc(loop->watchers, | ||
(nwatchers + 2) * sizeof(loop->watchers[0])); | ||
|
||
if (watchers == NULL) | ||
abort(); | ||
|
||
/* Copy watchers, preserving fake one in the end */ | ||
if (loop->watchers == NULL) { | ||
fake_watcher_list = watchers[loop->nwatchers]; | ||
fake_watcher_count = watchers[loop->nwatchers + 1]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using loop->watchers here would be a little clearer. |
||
} else { | ||
fake_watcher_list = NULL; | ||
fake_watcher_count = NULL; | ||
} | ||
for (i = loop->nwatchers; i < nwatchers; i++) | ||
watchers[i] = NULL; | ||
watchers[nwatchers] = fake_watcher_list; | ||
watchers[nwatchers + 1] = fake_watcher_count; | ||
|
||
loop->watchers = watchers; | ||
loop->nwatchers = nwatchers; | ||
|
@@ -700,6 +713,9 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { | |
void uv__io_close(uv_loop_t* loop, uv__io_t* w) { | ||
uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT); | ||
ngx_queue_remove(&w->pending_queue); | ||
|
||
/* Remove stale events for this file descriptor */ | ||
uv__platform_invalidate_fd(loop, w->fd); | ||
} | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,6 +102,25 @@ void uv__platform_loop_delete(uv_loop_t* loop) { | |
} | ||
|
||
|
||
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { | ||
struct kevent* events; | ||
uintptr_t i; | ||
uintptr_t nfds; | ||
|
||
assert(loop->watchers != NULL); | ||
|
||
events = (struct kevent*) loop->watchers[loop->nwatchers]; | ||
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; | ||
if (events == NULL) | ||
return; | ||
|
||
/* Invalidate events with same file descriptor */ | ||
for (i = 0; i < nfds; i++) | ||
if ((int) events[i].ident == fd) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd cast fd to uintptr_t here. Casts from unsigned to signed types of equal or smaller width are implementation defined. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. erm... we are doing the same thing in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's something we should fix then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In another PR, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. |
||
events[i].ident = -1; | ||
} | ||
|
||
|
||
static void uv__cf_loop_runner(void* arg) { | ||
uv_loop_t* loop; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -162,11 +162,18 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { | |
|
||
nevents = 0; | ||
|
||
assert(loop->watchers != NULL); | ||
loop->watchers[loop->nwatchers] = (void*) events; | ||
loop->watchers[loop->nwatchers + 1] = (void*) ((uintptr_t) nfds); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Superfluous parentheses. |
||
for (i = 0; i < nfds; i++) { | ||
ev = events + i; | ||
fd = ev->ident; | ||
w = loop->watchers[fd]; | ||
|
||
/* Skip invalidated events */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe point to uv__platform_invalidate_fd() here, else future readers will wonder how the fd became -1 all of a sudden. |
||
if (fd == -1) | ||
continue; | ||
|
||
if (w == NULL) { | ||
/* File descriptor that we've stopped watching, disarm it. */ | ||
/* TODO batch up */ | ||
|
@@ -227,6 +234,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { | |
w->cb(loop, w, revents); | ||
nevents++; | ||
} | ||
loop->watchers[loop->nwatchers] = NULL; | ||
loop->watchers[loop->nwatchers + 1] = NULL; | ||
|
||
if (nevents != 0) { | ||
if (nfds == ARRAY_SIZE(events) && --count != 0) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is unsound. Say that len == 14. In that case, next_power_of_two(14 + 2) - 2 is still 14.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, and that's ok. Since I'm allocating
nwatchers + 2
below.