Browse Source

upgrade libuv to 6e50576

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
133036fdad
  1. 2
      deps/uv/include/uv-win.h
  2. 2
      deps/uv/include/uv.h
  3. 1
      deps/uv/msvs/libuv-test.vcxproj
  4. 5
      deps/uv/src/uv-unix.c
  5. 34
      deps/uv/src/win/core.c
  6. 6
      deps/uv/src/win/error.c
  7. 25
      deps/uv/src/win/handle.c
  8. 1
      deps/uv/src/win/internal.h
  9. 170
      deps/uv/src/win/pipe.c
  10. 5
      deps/uv/test/test-async.c
  11. 9
      deps/uv/test/test-callback-stack.c
  12. 9
      deps/uv/test/test-delayed-accept.c
  13. 83
      deps/uv/test/test-idle.c
  14. 4
      deps/uv/test/test-list.h
  15. 20
      deps/uv/test/test-loop-handles.c
  16. 11
      src/handle_wrap.cc

2
deps/uv/include/uv-win.h

@ -103,7 +103,7 @@ typedef struct uv_buf_t {
HANDLE handle;
#define UV_PIPE_PRIVATE_FIELDS \
char* name; \
wchar_t* name; \
union { \
struct { uv_pipe_server_fields }; \
struct { uv_pipe_connection_fields }; \

2
deps/uv/include/uv.h

@ -229,7 +229,7 @@ int uv_is_active(uv_handle_t* handle);
* Request handle to be closed. close_cb will be called asynchronously after
* this call. This MUST be called on each handle before memory is released.
*/
int uv_close(uv_handle_t* handle, uv_close_cb close_cb);
void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
#define UV_STREAM_FIELDS \

1
deps/uv/msvs/libuv-test.vcxproj

@ -153,6 +153,7 @@
<ClCompile Include="..\test\test-getaddrinfo.c" />
<ClCompile Include="..\test\test-getsockname.c" />
<ClCompile Include="..\test\test-hrtime.c" />
<ClCompile Include="..\test\test-idle.c" />
<ClCompile Include="..\test\test-loop-handles.c" />
<ClCompile Include="..\test\test-pass-always.c" />
<ClCompile Include="..\test\test-ping-pong.c" />

5
deps/uv/src/uv-unix.c

@ -186,7 +186,7 @@ static uv_err_t uv_err_new(uv_handle_t* handle, int sys_error) {
}
int uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
uv_tcp_t* tcp;
uv_pipe_t* pipe;
uv_async_t* async;
@ -245,7 +245,6 @@ int uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
default:
assert(0);
return -1;
}
uv_flag_set(handle, UV_CLOSING);
@ -254,8 +253,6 @@ int uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
ev_idle_start(EV_DEFAULT_ &handle->next_watcher);
ev_feed_event(EV_DEFAULT_ &handle->next_watcher, EV_IDLE);
assert(ev_is_pending(&handle->next_watcher));
return 0;
}

34
deps/uv/src/win/core.c

@ -85,20 +85,24 @@ void uv_unref() {
}
static void uv_poll() {
static void uv_poll(int block) {
BOOL success;
DWORD bytes;
DWORD bytes, timeout;
ULONG_PTR key;
OVERLAPPED* overlapped;
uv_req_t* req;
if (block) {
timeout = uv_get_poll_timeout();
} else {
timeout = 0;
}
success = GetQueuedCompletionStatus(LOOP->iocp,
&bytes,
&key,
&overlapped,
uv_get_poll_timeout());
uv_update_time();
timeout);
if (overlapped) {
/* Package was dequeued */
@ -118,30 +122,30 @@ static void uv_poll() {
int uv_run() {
while (1) {
while (LOOP->refs > 0) {
uv_update_time();
uv_process_timers();
/* Terrible: please fix me! */
while (LOOP->refs > 0 &&
(LOOP->idle_handles || LOOP->pending_reqs_tail || LOOP->endgame_handles)) {
/* Terrible: please fix me! */
/* Call idle callbacks if nothing to do. */
if (LOOP->pending_reqs_tail == NULL && LOOP->endgame_handles == NULL) {
uv_idle_invoke();
}
/* Completely flush all pending reqs and endgames. */
/* We do even when we just called the idle callbacks because those may */
/* have closed handles or started requests that short-circuited. */
while (LOOP->pending_reqs_tail || LOOP->endgame_handles) {
uv_process_endgames();
uv_process_reqs();
}
/* Call idle callbacks */
uv_idle_invoke();
}
if (LOOP->refs <= 0) {
break;
}
uv_prepare_invoke();
uv_poll();
uv_poll(LOOP->idle_handles == NULL);
uv_check_invoke();
}

6
deps/uv/src/win/error.c

@ -132,3 +132,9 @@ void uv_set_sys_error(int sys_errno) {
LOOP->last_error.code = uv_translate_sys_error(sys_errno);
LOOP->last_error.sys_errno_ = sys_errno;
}
void uv_set_error(uv_err_code code, int sys_errno) {
LOOP->last_error.code = code;
LOOP->last_error.sys_errno_ = sys_errno;
}

25
deps/uv/src/win/handle.c

@ -40,12 +40,12 @@ int uv_is_active(uv_handle_t* handle) {
/* TODO: integrate this with uv_close. */
static int uv_close_error(uv_handle_t* handle, uv_err_t e) {
static void uv_close_error(uv_handle_t* handle, uv_err_t e) {
uv_tcp_t* tcp;
uv_pipe_t* pipe;
if (handle->flags & UV_HANDLE_CLOSING) {
return 0;
return;
}
handle->error = e;
@ -66,7 +66,7 @@ static int uv_close_error(uv_handle_t* handle, uv_err_t e) {
if (tcp->reqs_pending == 0) {
uv_want_endgame(handle);
}
return 0;
return;
case UV_NAMED_PIPE:
pipe = (uv_pipe_t*)handle;
@ -75,45 +75,44 @@ static int uv_close_error(uv_handle_t* handle, uv_err_t e) {
if (pipe->reqs_pending == 0) {
uv_want_endgame(handle);
}
return 0;
return;
case UV_TIMER:
uv_timer_stop((uv_timer_t*)handle);
uv_want_endgame(handle);
return 0;
return;
case UV_PREPARE:
uv_prepare_stop((uv_prepare_t*)handle);
uv_want_endgame(handle);
return 0;
return;
case UV_CHECK:
uv_check_stop((uv_check_t*)handle);
uv_want_endgame(handle);
return 0;
return;
case UV_IDLE:
uv_idle_stop((uv_idle_t*)handle);
uv_want_endgame(handle);
return 0;
return;
case UV_ASYNC:
if (!((uv_async_t*)handle)->async_sent) {
uv_want_endgame(handle);
}
return 0;
return;
default:
/* Not supported */
assert(0);
return -1;
abort();
}
}
int uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
handle->close_cb = close_cb;
return uv_close_error(handle, uv_ok_);
uv_close_error(handle, uv_ok_);
}

1
deps/uv/src/win/internal.h

@ -215,6 +215,7 @@ void uv_fatal_error(const int errorno, const char* syscall);
uv_err_code uv_translate_sys_error(int sys_errno);
uv_err_t uv_new_sys_error(int sys_errno);
void uv_set_sys_error(int sys_errno);
void uv_set_error(uv_err_code code, int sys_errno);
#endif /* UV_WIN_INTERNAL_H_ */

170
deps/uv/src/win/pipe.c

@ -38,6 +38,7 @@ int uv_pipe_init(uv_pipe_t* handle) {
handle->reqs_pending = 0;
handle->pending_accepts = NULL;
handle->name = NULL;
handle->handle = INVALID_HANDLE_VALUE;
uv_counters()->pipe_init++;
@ -96,20 +97,18 @@ void uv_pipe_endgame(uv_pipe_t* handle) {
/* Creates a pipe server. */
/* TODO: make this work with UTF8 name */
int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
int i;
int i, errno, nameSize;
uv_pipe_accept_t* req;
if (!name) {
if (handle->flags & UV_HANDLE_BOUND) {
uv_set_sys_error(WSAEINVAL);
return -1;
}
/* Make our own copy of the pipe name */
handle->name = _strdup(name);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
if (!name) {
uv_set_sys_error(WSAEINVAL);
return -1;
}
for (i = 0; i < COUNTOF(handle->accept_reqs); i++) {
@ -121,8 +120,67 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
req->next_pending = NULL;
}
/* Convert name to UTF16. */
nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t);
handle->name = (wchar_t*)malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) {
uv_set_sys_error(GetLastError());
return -1;
}
/*
* Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
* If this fails then there's already a pipe server for the given pipe name.
*/
handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
65536,
65536,
0,
NULL);
if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) {
errno = GetLastError();
if (errno == ERROR_ACCESS_DENIED) {
uv_set_error(UV_EADDRINUSE, errno);
handle->error = LOOP->last_error;
handle->flags |= UV_HANDLE_BIND_ERROR;
} else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) {
uv_set_error(UV_EADDRNOTAVAIL, errno);
} else {
uv_set_sys_error(errno);
}
goto error;
}
if (uv_set_pipe_handle(handle, handle->accept_reqs[0].pipeHandle)) {
uv_set_sys_error(GetLastError());
goto error;
}
handle->flags |= UV_HANDLE_PIPESERVER;
handle->flags |= UV_HANDLE_BOUND;
return 0;
error:
if (handle->name) {
free(handle->name);
handle->name = NULL;
}
if (handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) {
CloseHandle(handle->accept_reqs[0].pipeHandle);
handle->accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE;
}
return -1;
}
@ -138,9 +196,9 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
assert(handle);
/* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait for the pipe to become available with WaitNamedPipe. */
while (WaitNamedPipe(handle->name, 30000)) {
while (WaitNamedPipeW(handle->name, 30000)) {
/* The pipe is now available, try to connect. */
pipeHandle = CreateFile(handle->name,
pipeHandle = CreateFileW(handle->name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
@ -174,10 +232,9 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
}
/* TODO: make this work with UTF8 name */
int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
const char* name, uv_connect_cb cb) {
int errno;
int errno, nameSize;
HANDLE pipeHandle;
handle->handle = INVALID_HANDLE_VALUE;
@ -187,7 +244,19 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
req->handle = (uv_stream_t*) handle;
req->cb = cb;
pipeHandle = CreateFile(name,
/* Convert name to UTF16. */
nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t);
handle->name = (wchar_t*)malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) {
errno = GetLastError();
goto error;
}
pipeHandle = CreateFileW(handle->name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
@ -198,11 +267,6 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
if (pipeHandle == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_PIPE_BUSY) {
/* Wait for the server to make a pipe instance available. */
handle->name = _strdup(name);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) {
errno = GetLastError();
goto error;
@ -228,6 +292,11 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
return 0;
error:
if (handle->name) {
free(handle->name);
handle->name = NULL;
}
if (pipeHandle != INVALID_HANDLE_VALUE) {
CloseHandle(pipeHandle);
}
@ -243,7 +312,7 @@ void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) {
if (handle->name) {
free(handle->name);
handle->name;
handle->name = NULL;
}
if (handle->flags & UV_HANDLE_PIPESERVER) {
@ -251,24 +320,26 @@ void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) {
pipeHandle = handle->accept_reqs[i].pipeHandle;
if (pipeHandle != INVALID_HANDLE_VALUE) {
CloseHandle(pipeHandle);
handle->accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;
}
}
} else if (handle->handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle->handle);
handle->handle = INVALID_HANDLE_VALUE;
}
handle->flags |= UV_HANDLE_SHUT;
}
static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req) {
HANDLE pipeHandle;
static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL firstInstance) {
assert(handle->flags & UV_HANDLE_LISTENING);
if (!firstInstance) {
assert(req->pipeHandle == INVALID_HANDLE_VALUE);
pipeHandle = CreateNamedPipe(handle->name,
req->pipeHandle = CreateNamedPipeW(handle->name,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
@ -277,31 +348,34 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req) {
0,
NULL);
if (pipeHandle == INVALID_HANDLE_VALUE) {
if (req->pipeHandle == INVALID_HANDLE_VALUE) {
req->error = uv_new_sys_error(GetLastError());
uv_insert_pending_req((uv_req_t*) req);
handle->reqs_pending++;
return;
}
if (CreateIoCompletionPort(pipeHandle,
LOOP->iocp,
(ULONG_PTR)handle,
0) == NULL) {
if (uv_set_pipe_handle(handle, req->pipeHandle)) {
CloseHandle(req->pipeHandle);
req->pipeHandle = INVALID_HANDLE_VALUE;
req->error = uv_new_sys_error(GetLastError());
uv_insert_pending_req((uv_req_t*) req);
handle->reqs_pending++;
return;
}
}
assert(req->pipeHandle != INVALID_HANDLE_VALUE);
/* Prepare the overlapped structure. */
memset(&(req->overlapped), 0, sizeof(req->overlapped));
if (!ConnectNamedPipe(pipeHandle, &req->overlapped) && GetLastError() != ERROR_IO_PENDING) {
if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && GetLastError() != ERROR_IO_PENDING) {
if (GetLastError() == ERROR_PIPE_CONNECTED) {
req->pipeHandle = pipeHandle;
req->error = uv_ok_;
} else {
CloseHandle(req->pipeHandle);
req->pipeHandle = INVALID_HANDLE_VALUE;
/* Make this req pending reporting an error. */
req->error = uv_new_sys_error(GetLastError());
}
@ -310,7 +384,6 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req) {
return;
}
req->pipeHandle = pipeHandle;
handle->reqs_pending++;
}
@ -336,7 +409,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) {
req->pipeHandle = INVALID_HANDLE_VALUE;
if (!(server->flags & UV_HANDLE_CLOSING)) {
uv_pipe_queue_accept(server, req);
uv_pipe_queue_accept(server, req, FALSE);
}
return 0;
@ -347,22 +420,35 @@ int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) {
int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb) {
int i, errno;
if (handle->flags & UV_HANDLE_BIND_ERROR) {
LOOP->last_error = handle->error;
return -1;
}
if (!(handle->flags & UV_HANDLE_BOUND)) {
uv_set_error(UV_ENOTCONN, 0);
return -1;
}
if (handle->flags & UV_HANDLE_LISTENING ||
handle->flags & UV_HANDLE_READING) {
uv_set_sys_error(UV_EALREADY);
uv_set_error(UV_EALREADY, 0);
return -1;
}
if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
uv_set_sys_error(UV_ENOTSUP);
uv_set_error(UV_ENOTSUP, 0);
return -1;
}
handle->flags |= UV_HANDLE_LISTENING;
handle->connection_cb = cb;
/* First pipe handle should have already been created in uv_pipe_bind */
assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);
for (i = 0; i < COUNTOF(handle->accept_reqs); i++) {
uv_pipe_queue_accept(handle, &handle->accept_reqs[i]);
uv_pipe_queue_accept(handle, &handle->accept_reqs[i], i == 0);
}
return 0;
@ -403,17 +489,17 @@ static void uv_pipe_queue_read(uv_pipe_t* handle) {
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb) {
if (!(handle->flags & UV_HANDLE_CONNECTION)) {
uv_set_sys_error(UV_EINVAL);
uv_set_error(UV_EINVAL, 0);
return -1;
}
if (handle->flags & UV_HANDLE_READING) {
uv_set_sys_error(UV_EALREADY);
uv_set_error(UV_EALREADY, 0);
return -1;
}
if (handle->flags & UV_HANDLE_EOF) {
uv_set_sys_error(UV_EOF);
uv_set_error(UV_EOF, 0);
return -1;
}
@ -435,19 +521,19 @@ int uv_pipe_write(uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcn
int result;
if (bufcnt != 1) {
uv_set_sys_error(UV_ENOTSUP);
uv_set_error(UV_ENOTSUP, 0);
return -1;
}
assert(handle->handle != INVALID_HANDLE_VALUE);
if (!(handle->flags & UV_HANDLE_CONNECTION)) {
uv_set_sys_error(UV_EINVAL);
uv_set_error(UV_EINVAL, 0);
return -1;
}
if (handle->flags & UV_HANDLE_SHUTTING) {
uv_set_sys_error(UV_EOF);
uv_set_error(UV_EOF, 0);
return -1;
}
@ -485,7 +571,7 @@ int uv_pipe_write(uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcn
void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) {
DWORD bytes, avail, err, mode;
DWORD bytes, avail;
uv_buf_t buf;
assert(handle->type == UV_NAMED_PIPE);
@ -601,7 +687,7 @@ void uv_process_pipe_accept_req(uv_pipe_t* handle, uv_req_t* raw_req) {
req->pipeHandle = INVALID_HANDLE_VALUE;
}
if (!(handle->flags & UV_HANDLE_CLOSING)) {
uv_pipe_queue_accept(handle, req);
uv_pipe_queue_accept(handle, req, FALSE);
}
}

5
deps/uv/test/test-async.c

@ -146,8 +146,6 @@ static void async2_cb(uv_handle_t* handle, int status) {
static void prepare_cb(uv_prepare_t* handle, int status) {
int r;
ASSERT(handle == &prepare_handle);
ASSERT(status == 0);
@ -170,8 +168,7 @@ static void prepare_cb(uv_prepare_t* handle, int status) {
#endif
case 1:
r = uv_close((uv_handle_t*)handle, close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)handle, close_cb);
break;
default:

9
deps/uv/test/test-callback-stack.c

@ -83,9 +83,7 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
ASSERT(uv_last_error().code == UV_EOF);
nested++;
if (uv_close((uv_handle_t*)tcp, close_cb)) {
FATAL("uv_close failed");
}
uv_close((uv_handle_t*)tcp, close_cb);
nested--;
return;
@ -111,8 +109,6 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
static void timer_cb(uv_timer_t* handle, int status) {
int r;
ASSERT(handle == &timer);
ASSERT(status == 0);
ASSERT(nested == 0 && "timer_cb must be called from a fresh stack");
@ -127,8 +123,7 @@ static void timer_cb(uv_timer_t* handle, int status) {
timer_cb_called++;
r = uv_close((uv_handle_t*)handle, close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)handle, close_cb);
}

9
deps/uv/test/test-delayed-accept.c

@ -71,18 +71,15 @@ static void do_accept(uv_timer_t* timer_handle, int status) {
do_accept_called++;
/* Immediately close the accepted handle. */
r = uv_close((uv_handle_t*)accepted_handle, close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)accepted_handle, close_cb);
/* After accepting the two clients close the server handle */
if (do_accept_called == 2) {
r = uv_close((uv_handle_t*)server, close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)server, close_cb);
}
/* Dispose the timer. */
r = uv_close((uv_handle_t*)timer_handle, close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)timer_handle, close_cb);
}

83
deps/uv/test/test-idle.c

@ -0,0 +1,83 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
static uv_timer_t timer_handle;
static uv_idle_t idle_handle;
static int idle_cb_called = 0;
static int timer_cb_called = 0;
static int close_cb_called = 0;
static void close_cb(uv_handle_t* handle) {
close_cb_called++;
}
static void timer_cb(uv_timer_t* handle, int status) {
ASSERT(handle == &timer_handle);
ASSERT(status == 0);
uv_close((uv_handle_t*) &idle_handle, close_cb);
uv_close((uv_handle_t*) &timer_handle, close_cb);
timer_cb_called++;
LOGF("timer_cb %d\n", timer_cb_called);
}
static void idle_cb(uv_idle_t* handle, int status) {
ASSERT(handle == &idle_handle);
ASSERT(status == 0);
idle_cb_called++;
LOGF("idle_cb %d\n", idle_cb_called);
}
TEST_IMPL(idle_starvation) {
int r;
uv_init();
r = uv_idle_init(&idle_handle);
ASSERT(r == 0);
r = uv_idle_start(&idle_handle, idle_cb);
ASSERT(r == 0);
r = uv_timer_init(&timer_handle);
ASSERT(r == 0);
r = uv_timer_start(&timer_handle, timer_cb, 50, 0);
ASSERT(r == 0);
r = uv_run();
ASSERT(r == 0);
ASSERT(idle_cb_called > 0);
ASSERT(timer_cb_called == 1);
ASSERT(close_cb_called == 2);
return 0;
}

4
deps/uv/test/test-list.h

@ -46,6 +46,7 @@ TEST_DECLARE (shutdown_eof)
TEST_DECLARE (callback_stack)
TEST_DECLARE (timer)
TEST_DECLARE (timer_again)
TEST_DECLARE (idle_starvation)
TEST_DECLARE (loop_handles)
TEST_DECLARE (ref)
TEST_DECLARE (idle_ref)
@ -113,6 +114,8 @@ TASK_LIST_START
TEST_ENTRY (timer_again)
TEST_ENTRY (idle_starvation)
TEST_ENTRY (ref)
TEST_ENTRY (idle_ref)
TEST_ENTRY (async_ref)
@ -141,4 +144,3 @@ TASK_LIST_START
TEST_ENTRY (pass_always)
#endif
TASK_LIST_END

20
deps/uv/test/test-loop-handles.c

@ -130,8 +130,6 @@ static void idle_2_close_cb(uv_handle_t* handle) {
static void idle_2_cb(uv_idle_t* handle, int status) {
int r;
LOG("IDLE_2_CB\n");
ASSERT(handle == &idle_2_handle);
@ -139,8 +137,7 @@ static void idle_2_cb(uv_idle_t* handle, int status) {
idle_2_cb_called++;
r = uv_close((uv_handle_t*)handle, idle_2_close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)handle, idle_2_close_cb);
}
@ -230,23 +227,18 @@ static void check_cb(uv_check_t* handle, int status) {
} else {
/* End of the test - close all handles */
r = uv_close((uv_handle_t*)&prepare_1_handle, prepare_1_close_cb);
ASSERT(r == 0);
r = uv_close((uv_handle_t*)&check_handle, check_close_cb);
ASSERT(r == 0);
r = uv_close((uv_handle_t*)&prepare_2_handle, prepare_2_close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)&prepare_1_handle, prepare_1_close_cb);
uv_close((uv_handle_t*)&check_handle, check_close_cb);
uv_close((uv_handle_t*)&prepare_2_handle, prepare_2_close_cb);
for (i = 0; i < IDLE_COUNT; i++) {
r = uv_close((uv_handle_t*)&idle_1_handles[i], idle_1_close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)&idle_1_handles[i], idle_1_close_cb);
}
/* This handle is closed/recreated every time, close it only if it is */
/* active.*/
if (idle_2_is_active) {
r = uv_close((uv_handle_t*)&idle_2_handle, idle_2_close_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)&idle_2_handle, idle_2_close_cb);
}
}

11
src/handle_wrap.cc

@ -40,18 +40,11 @@ Handle<Value> HandleWrap::Close(const Arguments& args) {
UNWRAP
assert(!wrap->object_.IsEmpty());
int r = uv_close(wrap->handle__, OnClose);
uv_close(wrap->handle__, OnClose);
wrap->StateChange();
if (r) {
SetErrno(uv_last_error().code);
wrap->object_->SetPointerInInternalField(0, NULL);
wrap->object_.Dispose();
wrap->object_.Clear();
}
return scope.Close(Integer::New(r));
return v8::Null();
}

Loading…
Cancel
Save