upgrade libuv to 6e50576
authorRyan Dahl <ry@tinyclouds.org>
Thu, 21 Jul 2011 02:55:12 +0000 (19:55 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Thu, 21 Jul 2011 02:57:03 +0000 (19:57 -0700)
16 files changed:
deps/uv/include/uv-win.h
deps/uv/include/uv.h
deps/uv/msvs/libuv-test.vcxproj
deps/uv/src/uv-unix.c
deps/uv/src/win/core.c
deps/uv/src/win/error.c
deps/uv/src/win/handle.c
deps/uv/src/win/internal.h
deps/uv/src/win/pipe.c
deps/uv/test/test-async.c
deps/uv/test/test-callback-stack.c
deps/uv/test/test-delayed-accept.c
deps/uv/test/test-idle.c [new file with mode: 0644]
deps/uv/test/test-list.h
deps/uv/test/test-loop-handles.c
src/handle_wrap.cc

index 12588e9..5bbb446 100644 (file)
@@ -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 }; \
index f065b9d..6f302dc 100644 (file)
@@ -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 \
index 8408735..da93bd9 100644 (file)
     <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" />
index e614f0f..ff1f80d 100644 (file)
@@ -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;
 }
 
 
index e2d5a32..ed870ef 100644 (file)
@@ -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! */
-      while (LOOP->pending_reqs_tail || LOOP->endgame_handles) {
-        uv_process_endgames();
-        uv_process_reqs();
-      }
-
-      /* Call idle callbacks */
+    /* 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();
+    }
+
     if (LOOP->refs <= 0) {
       break;
     }
 
     uv_prepare_invoke();
 
-    uv_poll();
+    uv_poll(LOOP->idle_handles == NULL);
 
     uv_check_invoke();
   }
index d44be2b..4c2cacd 100644 (file)
@@ -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;
+}
index 91dfba8..cc6d2f8 100644 (file)
@@ -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_);
 }
 
 
index 33783f6..87b9c37 100644 (file)
@@ -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_ */
index e58b997..0481830 100644 (file)
@@ -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,57 +320,62 @@ 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);
-  assert(req->pipeHandle == INVALID_HANDLE_VALUE);
 
-  pipeHandle = CreateNamedPipe(handle->name,
-                               PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
-                               PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
-                               PIPE_UNLIMITED_INSTANCES,
-                               65536,
-                               65536,
-                               0,
-                               NULL);
+  if (!firstInstance) {
+    assert(req->pipeHandle == INVALID_HANDLE_VALUE);
 
-  if (pipeHandle == INVALID_HANDLE_VALUE) {
-    req->error = uv_new_sys_error(GetLastError());
-    uv_insert_pending_req((uv_req_t*) req);
-    handle->reqs_pending++;
-    return;
-  }
+    req->pipeHandle = CreateNamedPipeW(handle->name,
+                                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+                                       PIPE_UNLIMITED_INSTANCES,
+                                       65536,
+                                       65536,
+                                       0,
+                                       NULL);
 
-  if (CreateIoCompletionPort(pipeHandle,
-                                LOOP->iocp,
-                                (ULONG_PTR)handle,
-                                0) == NULL) {
-    req->error = uv_new_sys_error(GetLastError());
-    uv_insert_pending_req((uv_req_t*) req);
-    handle->reqs_pending++;
-    return;
+    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 (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);
     }
   }
 
index f91d9b4..2a3a1bf 100644 (file)
@@ -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:
index 4162b22..6582010 100644 (file)
@@ -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);
 }
 
 
index 30b63b9..8e3dfc1 100644 (file)
@@ -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);
 }
 
 
diff --git a/deps/uv/test/test-idle.c b/deps/uv/test/test-idle.c
new file mode 100644 (file)
index 0000000..46917d0
--- /dev/null
@@ -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;
+}
index d1edcd3..8b9ecfc 100644 (file)
@@ -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
-
index 7979a74..2e858c1 100644 (file)
@@ -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);
     }
   }
 
index c34c1c2..140b8ba 100644 (file)
@@ -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();
 }