Showing with 285 additions and 3 deletions.
  1. +1 −0 checksparse.sh
  2. +19 −3 src/unix/core.c
  3. +19 −0 src/unix/darwin.c
  4. +1 −0 src/unix/internal.h
  5. +9 −0 src/unix/kqueue.c
  6. +28 −0 src/unix/linux-core.c
  7. +28 −0 src/unix/sunos.c
  8. +2 −0 test/test-list.h
  9. +177 −0 test/test-tcp-close-accept.c
  10. +1 −0 uv.gyp
@@ -132,6 +132,7 @@ test/test-stdio-over-pipes.c
test/test-tcp-bind-error.c
test/test-tcp-bind6-error.c
test/test-tcp-close-while-connecting.c
test/test-tcp-close-accept.c
test/test-tcp-close.c
test/test-tcp-connect-error-after-write.c
test/test-tcp-connect-error.c
@@ -604,20 +604,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]));
/* Preserve fake watcher list and count at the end of the watchers */
if (loop->watchers != NULL) {
fake_watcher_list = loop->watchers[loop->nwatchers];
fake_watcher_count = loop->watchers[loop->nwatchers + 1];
} else {
fake_watcher_list = NULL;
fake_watcher_count = NULL;
}

nwatchers = next_power_of_two(len + 2) - 2;
watchers = realloc(loop->watchers,
(nwatchers + 2) * sizeof(loop->watchers[0]));

if (watchers == NULL)
abort();

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;
@@ -709,6 +722,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);
QUEUE_REMOVE(&w->pending_queue);

/* Remove stale events for this file descriptor */
uv__platform_invalidate_fd(loop, w->fd);
}


@@ -52,6 +52,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)
events[i].ident = -1;
}


uint64_t uv__hrtime(uv_clocktype_t type) {
mach_timebase_info_data_t info;

@@ -200,6 +200,7 @@ uint64_t uv__hrtime(uv_clocktype_t type);
int uv__kqueue_init(uv_loop_t* loop);
int uv__platform_loop_init(uv_loop_t* loop, int default_loop);
void uv__platform_loop_delete(uv_loop_t* loop);
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);

/* various */
void uv__async_close(uv_async_t* handle);
@@ -161,11 +161,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;
for (i = 0; i < nfds; i++) {
ev = events + i;
fd = ev->ident;
w = loop->watchers[fd];

/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;

if (w == NULL) {
/* File descriptor that we've stopped watching, disarm it. */
/* TODO batch up */
@@ -226,6 +233,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) {
@@ -105,6 +105,25 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}


void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct uv__epoll_event* events;
uintptr_t i;
uintptr_t nfds;

assert(loop->watchers != NULL);

events = (struct uv__epoll_event*) 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].data == fd)
events[i].data = -1;
}


void uv__io_poll(uv_loop_t* loop, int timeout) {
struct uv__epoll_event events[1024];
struct uv__epoll_event* pe;
@@ -197,10 +216,17 @@ 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;
for (i = 0; i < nfds; i++) {
pe = events + i;
fd = pe->data;

/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;

assert(fd >= 0);
assert((unsigned) fd < loop->nwatchers);

@@ -246,6 +272,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
nevents++;
}
}
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;

if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
@@ -97,6 +97,25 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}


void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct port_event* events;
uintptr_t i;
uintptr_t nfds;

assert(loop->watchers != NULL);

events = (struct port_event*) 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].portev_object == fd)
events[i].portev_object = -1;
}


void uv__io_poll(uv_loop_t* loop, int timeout) {
struct port_event events[1024];
struct port_event* pe;
@@ -183,10 +202,17 @@ 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;
for (i = 0; i < nfds; i++) {
pe = events + i;
fd = pe->portev_object;

/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;

assert(fd >= 0);
assert((unsigned) fd < loop->nwatchers);

@@ -206,6 +232,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue))
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
}
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;

if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
@@ -65,6 +65,7 @@ TEST_DECLARE (tcp_connect_error_fault)
TEST_DECLARE (tcp_connect_timeout)
TEST_DECLARE (tcp_close_while_connecting)
TEST_DECLARE (tcp_close)
TEST_DECLARE (tcp_close_accept)
TEST_DECLARE (tcp_flags)
TEST_DECLARE (tcp_write_to_half_open_connection)
TEST_DECLARE (tcp_unexpected_read)
@@ -306,6 +307,7 @@ TASK_LIST_START
TEST_ENTRY (tcp_connect_timeout)
TEST_ENTRY (tcp_close_while_connecting)
TEST_ENTRY (tcp_close)
TEST_ENTRY (tcp_close_accept)
TEST_ENTRY (tcp_flags)
TEST_ENTRY (tcp_write_to_half_open_connection)
TEST_ENTRY (tcp_unexpected_read)