uv: Upgrade to v0.11.17
authorTimothy J Fontaine <tjfontaine@gmail.com>
Tue, 31 Dec 2013 18:33:54 +0000 (10:33 -0800)
committerTimothy J Fontaine <tjfontaine@gmail.com>
Tue, 31 Dec 2013 18:33:54 +0000 (10:33 -0800)
24 files changed:
deps/uv/.gitignore
deps/uv/.mailmap
deps/uv/AUTHORS
deps/uv/ChangeLog
deps/uv/Makefile.am
deps/uv/README.md
deps/uv/checksparse.sh
deps/uv/include/uv.h
deps/uv/src/unix/core.c
deps/uv/src/unix/fs.c
deps/uv/src/unix/kqueue.c
deps/uv/src/unix/stream.c
deps/uv/src/version.c
deps/uv/src/win/core.c
deps/uv/src/win/pipe.c
deps/uv/src/win/stream.c
deps/uv/test/test-ip4-addr.c
deps/uv/test/test-list.h
deps/uv/test/test-loop-alive.c [new file with mode: 0644]
deps/uv/test/test-pipe-server-close.c [new file with mode: 0644]
deps/uv/test/test-spawn.c
deps/uv/test/test-tcp-try-write.c
deps/uv/uv.gyp
deps/uv/vcbuild.bat

index c8d93d8..d11c90b 100644 (file)
@@ -37,6 +37,9 @@ Makefile.in
 # Generated by dtrace(1) when doing an in-tree build.
 /include/uv-dtrace.h
 
+# Generated by gyp for android
+*.target.mk
+
 /out/
 /build/gyp
 
index a1e5f71..5c76ed7 100644 (file)
@@ -1,4 +1,5 @@
 Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
+Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
 Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
 Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
 Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
index a7c48c4..9cb892c 100644 (file)
@@ -108,3 +108,5 @@ Andrej Manduch <AManduch@gmail.com>
 Joshua Neuheisel <joshua@neuheisel.us>
 Alexis Campailla <alexis@janeasystems.com>
 Yorkie <yorkiefixer@gmail.com>
+Sam Roberts <vieuxtech@gmail.com>
+River Tarnell <river@loreley.flyingparchment.org.uk>
index 5ee5338..cff1046 100644 (file)
@@ -1,3 +1,20 @@
+2013.12.32, Version 0.11.17 (Unstable)
+
+Changes since version 0.11.16:
+
+* stream: allow multiple buffers for uv_try_write (Fedor Indutny)
+
+* unix: fix a possible memory leak in uv_fs_readdir (Alex Crichton)
+
+* unix, windows: add uv_loop_alive() function (Sam Roberts)
+
+* windows: avoid assertion failure when pipe server is closed (Bert Belder)
+
+* osx: Fix a possible segfault in uv__io_poll (Alex Crichton)
+
+* stream: fix uv__stream_osx_select (Fedor Indutny)
+
+
 2013.12.14, Version 0.11.16 (Unstable), ae0ed8c49d0d313c935c22077511148b6e8408a4
 
 Changes since version 0.11.15:
index 2229e86..c1eae8c 100644 (file)
@@ -145,6 +145,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
                          test/test-ipc.c \
                          test/test-list.h \
                          test/test-loop-handles.c \
+                         test/test-loop-alive.c \
                          test/test-loop-stop.c \
                          test/test-loop-time.c \
                          test/test-multiple-listen.c \
@@ -154,6 +155,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
                          test/test-ping-pong.c \
                          test/test-pipe-bind-error.c \
                          test/test-pipe-connect-error.c \
+                         test/test-pipe-server-close.c \
                          test/test-platform-output.c \
                          test/test-poll-close.c \
                          test/test-poll.c \
index 0b0f17f..526b2c5 100644 (file)
@@ -4,7 +4,7 @@ libuv is a multi-platform support library with a focus on asynchronous I/O. It
 was primarily developed for use by [Node.js](http://nodejs.org), but it's also
 used by Mozilla's [Rust language](http://www.rust-lang.org/),
 [Luvit](http://luvit.io/), [Julia](http://julialang.org/),
-[pyuv](https://crate.io/packages/pyuv/), and others.
+[pyuv](https://crate.io/packages/pyuv/), and [others](https://github.com/joyent/libuv/wiki/Projects-that-use-libuv).
 
 ## Feature highlights
 
@@ -41,12 +41,14 @@ used by Mozilla's [Rust language](http://www.rust-lang.org/),
 
  * [include/uv.h](https://github.com/joyent/libuv/blob/master/include/uv.h)
    &mdash; API documentation in the form of detailed header comments.
- * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) &mdash; An
-   overview of libuv with tutorials.
- * [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4) - High-level
-   introductory talk about libuv.
- * [Tests and benchmarks](https://github.com/joyent/libuv/tree/master/test) -
-   API specification and usage examples.
+ * [An Introduction to libuv](http://nikhilm.github.com/uvbook/)
+   &mdash; An overview of libuv with tutorials.
+ * [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4)
+   &mdash; High-level introductory talk about libuv.
+ * [Tests and benchmarks](https://github.com/joyent/libuv/tree/master/test)
+   &mdash; API specification and usage examples.
+ * [libuv-dox](https://github.com/thlorenz/libuv-dox)
+   &mdash; Documenting types and methods of libuv, mostly by reading uv.h.
 
 ## Build Instructions
 
index b1d8187..54cd580 100755 (executable)
@@ -115,6 +115,7 @@ test/test-pass-always.c
 test/test-ping-pong.c
 test/test-pipe-bind-error.c
 test/test-pipe-connect-error.c
+test/test-pipe-server-close.c
 test/test-platform-output.c
 test/test-poll-close.c
 test/test-poll.c
index d6485e5..505b024 100644 (file)
@@ -273,6 +273,12 @@ UV_EXTERN uv_loop_t* uv_default_loop(void);
 UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
 
 /*
+ * This function checks whether the reference count, the number of active
+ * handles or requests left in the event loop, is non-zero.
+ */
+UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);
+
+/*
  * This function will stop the event loop by forcing uv_run to end
  * as soon as possible, but not sooner than the next loop iteration.
  * If this function was called before blocking for i/o, the loop won't
@@ -681,7 +687,9 @@ UV_EXTERN int uv_write2(uv_write_t* req,
  * - zero - if queued write is needed
  * - negative error code
  */
-UV_EXTERN int uv_try_write(uv_stream_t* handle, const char* buf, size_t length);
+UV_EXTERN int uv_try_write(uv_stream_t* handle,
+                           const uv_buf_t bufs[],
+                           unsigned int nbufs);
 
 /* uv_write_t is a subclass of uv_req_t */
 struct uv_write_s {
index 6bb2057..df2a5f8 100644 (file)
@@ -248,13 +248,18 @@ int uv_backend_timeout(const uv_loop_t* loop) {
 }
 
 
-static int uv__loop_alive(uv_loop_t* loop) {
+static int uv__loop_alive(const uv_loop_t* loop) {
   return uv__has_active_handles(loop) ||
          uv__has_active_reqs(loop) ||
          loop->closing_handles != NULL;
 }
 
 
+int uv_loop_alive(const uv_loop_t* loop) {
+    return uv__loop_alive(loop);
+}
+
+
 int uv_run(uv_loop_t* loop, uv_run_mode mode) {
   int timeout;
   int r;
index 4e572b7..1aa6539 100644 (file)
@@ -213,9 +213,12 @@ static ssize_t uv__fs_readdir(uv_fs_t* req) {
   int i;
   int n;
 
+  dents = NULL;
   n = scandir(req->path, &dents, uv__fs_readdir_filter, alphasort);
 
-  if (n == -1 || n == 0)
+  if (n == 0)
+    goto out; /* osx still needs to deallocate some memory */
+  else if (n == -1)
     return n;
 
   len = 0;
@@ -243,7 +246,7 @@ static ssize_t uv__fs_readdir(uv_fs_t* req) {
 
 out:
   saved_errno = errno;
-  {
+  if (dents != NULL) {
     for (i = 0; i < n; i++)
       free(dents[i]);
     free(dents);
index 70f5d9e..f86f291 100644 (file)
@@ -167,11 +167,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
     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;
+      w = loop->watchers[fd];
 
       if (w == NULL) {
         /* File descriptor that we've stopped watching, disarm it. */
index afd2a05..9f5d40c 100644 (file)
@@ -138,6 +138,31 @@ void uv__stream_init(uv_loop_t* loop,
 }
 
 
+static void uv__stream_osx_interrupt_select(uv_stream_t* stream) {
+#if defined(__APPLE__)
+  /* Notify select() thread about state change */
+  uv__stream_select_t* s;
+  int r;
+
+  s = stream->select;
+  if (s == NULL)
+    return;
+
+  /* Interrupt select() loop
+   * NOTE: fake_fd and int_fd are socketpair(), thus writing to one will
+   * emit read event on other side
+   */
+  do
+    r = write(s->fake_fd, "x", 1);
+  while (r == -1 && errno == EINTR);
+
+  assert(r == 1);
+#else  /* !defined(__APPLE__) */
+  /* No-op on any other platform */
+#endif  /* !defined(__APPLE__) */
+}
+
+
 #if defined(__APPLE__)
 static void uv__stream_osx_select(void* arg) {
   uv_stream_t* stream;
@@ -168,9 +193,9 @@ static void uv__stream_osx_select(void* arg) {
     FD_ZERO(&sread);
     FD_ZERO(&swrite);
 
-    if (uv_is_readable(stream))
+    if (uv__io_active(&stream->io_watcher, UV__POLLIN))
       FD_SET(fd, &sread);
-    if (uv_is_writable(stream))
+    if (uv__io_active(&stream->io_watcher, UV__POLLOUT))
       FD_SET(fd, &swrite);
     FD_SET(s->int_fd, &sread);
 
@@ -229,25 +254,6 @@ static void uv__stream_osx_select(void* arg) {
 }
 
 
-static void uv__stream_osx_interrupt_select(uv_stream_t* stream) {
-  /* Notify select() thread about state change */
-  uv__stream_select_t* s;
-  int r;
-
-  s = stream->select;
-
-  /* Interrupt select() loop
-   * NOTE: fake_fd and int_fd are socketpair(), thus writing to one will
-   * emit read event on other side
-   */
-  do
-    r = write(s->fake_fd, "x", 1);
-  while (r == -1 && errno == EINTR);
-
-  assert(r == 1);
-}
-
-
 static void uv__stream_osx_select_cb(uv_async_t* handle, int status) {
   uv__stream_select_t* s;
   uv_stream_t* stream;
@@ -622,6 +628,7 @@ static void uv__drain(uv_stream_t* stream) {
 
   assert(QUEUE_EMPTY(&stream->write_queue));
   uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
+  uv__stream_osx_interrupt_select(stream);
 
   /* Shutdown? */
   if ((stream->flags & UV_STREAM_SHUTTING) &&
@@ -802,6 +809,7 @@ start:
       uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
       if (!uv__io_active(&stream->io_watcher, UV__POLLIN))
         uv__handle_stop(stream);
+      uv__stream_osx_interrupt_select(stream);
       return;
     } else if (stream->flags & UV_STREAM_BLOCKING) {
       /* If this is a blocking stream, try again. */
@@ -863,6 +871,9 @@ start:
 
   /* We're not done. */
   uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT);
+
+  /* Notify select() thread about state change */
+  uv__stream_osx_interrupt_select(stream);
 }
 
 
@@ -947,6 +958,7 @@ static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
   uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
   if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
     uv__handle_stop(stream);
+  uv__stream_osx_interrupt_select(stream);
   uv__stream_read_cb(stream, UV_EOF, buf, UV_UNKNOWN_HANDLE);
 }
 
@@ -1013,6 +1025,7 @@ static void uv__read(uv_stream_t* stream) {
         /* Wait for the next one. */
         if (stream->flags & UV_STREAM_READING) {
           uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
+          uv__stream_osx_interrupt_select(stream);
         }
         uv__stream_read_cb(stream, 0, &buf, UV_UNKNOWN_HANDLE);
       } else {
@@ -1105,6 +1118,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
   stream->flags |= UV_STREAM_SHUTTING;
 
   uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT);
+  uv__stream_osx_interrupt_select(stream);
 
   return 0;
 }
@@ -1281,6 +1295,7 @@ int uv_write2(uv_write_t* req,
      */
     assert(!(stream->flags & UV_STREAM_BLOCKING));
     uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT);
+    uv__stream_osx_interrupt_select(stream);
   }
 
   return 0;
@@ -1305,13 +1320,14 @@ void uv_try_write_cb(uv_write_t* req, int status) {
 }
 
 
-int uv_try_write(uv_stream_t* stream, const char* buf, size_t size) {
+int uv_try_write(uv_stream_t* stream,
+                 const uv_buf_t bufs[],
+                 unsigned int nbufs) {
   int r;
   int has_pollout;
   size_t written;
   size_t req_size;
   uv_write_t req;
-  uv_buf_t bufstruct;
 
   /* Connecting or already writing some data */
   if (stream->connect_req != NULL || stream->write_queue_size != 0)
@@ -1319,13 +1335,12 @@ int uv_try_write(uv_stream_t* stream, const char* buf, size_t size) {
 
   has_pollout = uv__io_active(&stream->io_watcher, UV__POLLOUT);
 
-  bufstruct = uv_buf_init((char*) buf, size);
-  r = uv_write(&req, stream, &bufstruct, 1, uv_try_write_cb);
+  r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb);
   if (r != 0)
     return r;
 
   /* Remove not written bytes from write queue size */
-  written = size;
+  written = uv_count_bufs(bufs, nbufs);
   if (req.bufs != NULL)
     req_size = uv__write_req_size(&req);
   else
@@ -1341,8 +1356,10 @@ int uv_try_write(uv_stream_t* stream, const char* buf, size_t size) {
   req.bufs = NULL;
 
   /* Do not poll for writable, if we wasn't before calling this */
-  if (!has_pollout)
+  if (!has_pollout) {
     uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
+    uv__stream_osx_interrupt_select(stream);
+  }
 
   return (int) written;
 }
@@ -1363,12 +1380,6 @@ static int uv__read_start_common(uv_stream_t* stream,
    */
   stream->flags |= UV_STREAM_READING;
 
-#if defined(__APPLE__)
-  /* Notify select() thread about state change */
-  if (stream->select != NULL)
-    uv__stream_osx_interrupt_select(stream);
-#endif /* defined(__APPLE__) */
-
   /* TODO: try to do the read inline? */
   /* TODO: keep track of tcp state. If we've gotten a EOF then we should
    * not start the IO watcher.
@@ -1382,6 +1393,7 @@ static int uv__read_start_common(uv_stream_t* stream,
 
   uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
   uv__handle_start(stream);
+  uv__stream_osx_interrupt_select(stream);
 
   return 0;
 }
@@ -1414,12 +1426,7 @@ int uv_read_stop(uv_stream_t* stream) {
   uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
   if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
     uv__handle_stop(stream);
-
-#if defined(__APPLE__)
-  /* Notify select() thread about state change */
-  if (stream->select != NULL)
-    uv__stream_osx_interrupt_select(stream);
-#endif /* defined(__APPLE__) */
+  uv__stream_osx_interrupt_select(stream);
 
   stream->read_cb = NULL;
   stream->read2_cb = NULL;
index c9e4200..d50fea7 100644 (file)
@@ -32,7 +32,7 @@
 #define UV_VERSION_MAJOR 0
 #define UV_VERSION_MINOR 11
 #define UV_VERSION_PATCH 17
-#define UV_VERSION_IS_RELEASE 0
+#define UV_VERSION_IS_RELEASE 1
 
 
 #define UV_VERSION  ((UV_VERSION_MAJOR << 16) | \
index 2eab49f..ddeb0bc 100644 (file)
@@ -256,13 +256,18 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
 }
 
 
-static int uv__loop_alive(uv_loop_t* loop) {
+static int uv__loop_alive(const uv_loop_t* loop) {
   return loop->active_handles > 0 ||
          !QUEUE_EMPTY(&loop->active_reqs) ||
          loop->endgame_handles != NULL;
 }
 
 
+int uv_loop_alive(const uv_loop_t* loop) {
+    return uv__loop_alive(loop);
+}
+
+
 int uv_run(uv_loop_t *loop, uv_run_mode mode) {
   int r;
   void (*poll)(uv_loop_t* loop, int block);
index 08f0167..a57a775 100644 (file)
@@ -1557,6 +1557,13 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
 
   assert(handle->type == UV_NAMED_PIPE);
 
+  if (handle->flags & UV__HANDLE_CLOSING) {
+    /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */
+    assert(req->pipeHandle == INVALID_HANDLE_VALUE);
+    DECREASE_PENDING_REQ_COUNT(handle);
+    return;
+  }
+
   if (REQ_SUCCESS(req)) {
     assert(req->pipeHandle != INVALID_HANDLE_VALUE);
     req->next_pending = handle->pending_accepts;
index da62883..2eaa74e 100644 (file)
@@ -202,7 +202,9 @@ int uv_write2(uv_write_t* req,
 }
 
 
-int uv_try_write(uv_stream_t* handle, const char* buf, size_t length) {
+int uv_try_write(uv_stream_t* stream,
+                 const uv_buf_t bufs[],
+                 unsigned int nbufs) {
   /* NOTE: Won't work with overlapped writes */
   return UV_ENOSYS;
 }
index fc61f50..3d6e0cf 100644 (file)
@@ -37,7 +37,7 @@ TEST_IMPL(ip4_addr) {
   ASSERT(UV_EINVAL == uv_ip4_addr("2555.0.0.0", TEST_PORT, &addr));
   ASSERT(UV_EINVAL == uv_ip4_addr("255", TEST_PORT, &addr));
 
-  // for broken address family
+  /* for broken address family */
   ASSERT(UV_EAFNOSUPPORT == uv_inet_pton(42, "127.0.0.1",
     &addr.sin_addr.s_addr));
 
index f744a20..2195e23 100644 (file)
@@ -24,6 +24,7 @@ TEST_DECLARE   (callback_order)
 TEST_DECLARE   (close_order)
 TEST_DECLARE   (run_once)
 TEST_DECLARE   (run_nowait)
+TEST_DECLARE   (loop_alive)
 TEST_DECLARE   (loop_stop)
 TEST_DECLARE   (loop_update_time)
 TEST_DECLARE   (barrier_1)
@@ -91,6 +92,7 @@ TEST_DECLARE   (pipe_bind_error_inval)
 TEST_DECLARE   (pipe_listen_without_bind)
 TEST_DECLARE   (pipe_connect_bad_name)
 TEST_DECLARE   (pipe_connect_to_file)
+TEST_DECLARE   (pipe_server_close)
 TEST_DECLARE   (connection_fail)
 TEST_DECLARE   (connection_fail_doesnt_auto_close)
 TEST_DECLARE   (shutdown_close_tcp)
@@ -253,6 +255,7 @@ TASK_LIST_START
   TEST_ENTRY  (close_order)
   TEST_ENTRY  (run_once)
   TEST_ENTRY  (run_nowait)
+  TEST_ENTRY  (loop_alive)
   TEST_ENTRY  (loop_stop)
   TEST_ENTRY  (loop_update_time)
   TEST_ENTRY  (barrier_1)
@@ -270,6 +273,7 @@ TASK_LIST_START
   TEST_ENTRY  (pipe_connect_bad_name)
   TEST_ENTRY  (pipe_connect_to_file)
 
+  TEST_ENTRY  (pipe_server_close)
   TEST_ENTRY  (tty)
   TEST_ENTRY  (stdio_over_pipes)
   TEST_ENTRY  (ipc_listen_before_write)
diff --git a/deps/uv/test/test-loop-alive.c b/deps/uv/test/test-loop-alive.c
new file mode 100644 (file)
index 0000000..8924335
--- /dev/null
@@ -0,0 +1,68 @@
+/* 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 void timer_cb(uv_timer_t* handle, int status) {
+  ASSERT(handle);
+  ASSERT(status == 0);
+}
+
+
+static uv_work_t work_req;
+
+static void work_cb(uv_work_t* req) {
+  ASSERT(req);
+}
+
+static void after_work_cb(uv_work_t* req, int status) {
+  ASSERT(req);
+  ASSERT(status == 0);
+}
+
+
+TEST_IMPL(loop_alive) {
+  int r;
+  ASSERT(!uv_loop_alive(uv_default_loop()));
+
+  /* loops with handles are alive */
+  uv_timer_init(uv_default_loop(), &timer_handle);
+  uv_timer_start(&timer_handle, timer_cb, 100, 0);
+  ASSERT(uv_loop_alive(uv_default_loop()));
+
+  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+  ASSERT(r == 0);
+  ASSERT(!uv_loop_alive(uv_default_loop()));
+
+  /* loops with requests are alive */
+  r = uv_queue_work(uv_default_loop(), &work_req, work_cb, after_work_cb);
+  ASSERT(r == 0);
+  ASSERT(uv_loop_alive(uv_default_loop()));
+
+  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+  ASSERT(r == 0);
+  ASSERT(!uv_loop_alive(uv_default_loop()));
+
+  return 0;
+}
diff --git a/deps/uv/test/test-pipe-server-close.c b/deps/uv/test/test-pipe-server-close.c
new file mode 100644 (file)
index 0000000..1dcdfff
--- /dev/null
@@ -0,0 +1,91 @@
+/* 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"
+
+#include <string.h>
+#include <errno.h>
+
+
+static uv_pipe_t pipe_client;
+static uv_pipe_t pipe_server;
+static uv_connect_t connect_req;
+
+static int pipe_close_cb_called = 0;
+static int pipe_client_connect_cb_called = 0;
+
+
+static void pipe_close_cb(uv_handle_t* handle) {
+  ASSERT(handle == (uv_handle_t*) &pipe_client ||
+         handle == (uv_handle_t*) &pipe_server);
+  pipe_close_cb_called++;
+}
+
+
+static void pipe_client_connect_cb(uv_connect_t* req, int status) {
+  ASSERT(req == &connect_req);
+  ASSERT(status == 0);
+
+  pipe_client_connect_cb_called++;
+
+  uv_close((uv_handle_t*) &pipe_client, pipe_close_cb);
+  uv_close((uv_handle_t*) &pipe_server, pipe_close_cb);
+}
+
+
+static void pipe_server_connection_cb(uv_stream_t* handle, int status) {
+  /* This function *may* be called, depending on whether accept or the
+   * connection callback is called first.
+   */
+  ASSERT(status == 0);
+}
+
+
+TEST_IMPL(pipe_server_close) {
+  uv_loop_t* loop;
+  int r;
+
+  loop = uv_default_loop();
+  ASSERT(loop != NULL);
+
+  r = uv_pipe_init(loop, &pipe_server, 0);
+  ASSERT(r == 0);
+
+  r = uv_pipe_bind(&pipe_server, TEST_PIPENAME);
+  ASSERT(r == 0);
+
+  r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb);
+  ASSERT(r == 0);
+
+  r = uv_pipe_init(loop, &pipe_client, 0);
+  ASSERT(r == 0);
+
+  uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb);
+
+  r = uv_run(loop, UV_RUN_DEFAULT);
+  ASSERT(r == 0);
+  ASSERT(pipe_client_connect_cb_called == 1);
+  ASSERT(pipe_close_cb_called == 2);
+
+  MAKE_VALGRIND_HAPPY();
+  return 0;
+}
index 0a355af..d11e5a8 100644 (file)
@@ -146,10 +146,13 @@ static void timer_cb(uv_timer_t* handle, int status) {
 
 
 TEST_IMPL(spawn_fails) {
+  int r;
+
   init_process_options("", fail_cb);
   options.file = options.args[0] = "program-that-had-better-not-exist";
 
-  ASSERT(UV_ENOENT == uv_spawn(uv_default_loop(), &process, &options));
+  r = uv_spawn(uv_default_loop(), &process, &options);
+  ASSERT(r == UV_ENOENT || r == UV_EACCES);
   ASSERT(0 == uv_is_active((uv_handle_t*) &process));
   ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
 
index 3fd6166..f4f4fb5 100644 (file)
@@ -61,7 +61,8 @@ static void connect_cb(uv_connect_t* req, int status) {
   connect_cb_called++;
 
   do {
-    r = uv_try_write((uv_stream_t*) &client, zeroes, sizeof(zeroes));
+    buf = uv_buf_init(zeroes, sizeof(zeroes));
+    r = uv_try_write((uv_stream_t*) &client, &buf, 1);
     ASSERT(r >= 0);
     bytes_written += r;
 
index 962efac..50e1935 100644 (file)
         'test/test-ipc-send-recv.c',
         'test/test-list.h',
         'test/test-loop-handles.c',
+        'test/test-loop-alive.c',
         'test/test-loop-stop.c',
         'test/test-loop-time.c',
         'test/test-walk-handles.c',
         'test/test-ping-pong.c',
         'test/test-pipe-bind-error.c',
         'test/test-pipe-connect-error.c',
+        'test/test-pipe-server-close.c',
         'test/test-platform-output.c',
         'test/test-poll.c',
         'test/test-poll-close.c',
index 0b7ea48..8545b26 100644 (file)
@@ -41,7 +41,15 @@ shift
 goto next-arg
 :args-done
 
+@rem Look for Visual Studio 2013
+if not defined VS120COMNTOOLS goto vc-set-2012
+if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012
+call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset%
+set GYP_MSVS_VERSION=2013
+goto select-target
+
 @rem Look for Visual Studio 2012
+:vc-set-2012
 if not defined VS110COMNTOOLS goto vc-set-2010
 if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010
 call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset%