uv: upgrade to a1adfe3
authorBen Noordhuis <info@bnoordhuis.nl>
Wed, 27 Jul 2011 01:54:00 +0000 (03:54 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Wed, 27 Jul 2011 01:54:00 +0000 (03:54 +0200)
20 files changed:
deps/uv/include/uv-unix.h
deps/uv/include/uv.h
deps/uv/msvs/libuv.vcxproj
deps/uv/src/uv-unix.c
deps/uv/src/win/internal.h
deps/uv/src/win/pipe.c
deps/uv/src/win/stdio.c [new file with mode: 0644]
deps/uv/src/win/stream.c
deps/uv/src/win/tcp.c
deps/uv/test/benchmark-pump.c
deps/uv/test/dns-server.c
deps/uv/test/echo-server.c
deps/uv/test/run-tests.c
deps/uv/test/test-delayed-accept.c
deps/uv/test/test-getsockname.c
deps/uv/test/test-list.h
deps/uv/test/test-pipe-bind-error.c
deps/uv/test/test-spawn.c [new file with mode: 0644]
deps/uv/test/test-tcp-bind-error.c
deps/uv/test/test-tcp-bind6-error.c

index cad2ed4abe9c56de3986ab5f413b17226d1f97fb..72c66a9f71fe5b557fda53258dad6d612fcefbf4 100644 (file)
@@ -132,4 +132,7 @@ typedef struct {
   struct addrinfo* res; \
   int retcode;
 
+#define UV_PROCESS_PRIVATE_FIELDS \
+  ev_child child_watcher;
+
 #endif /* UV_UNIX_H */
index 6f302dcd176061957961b414ad167947b4caf349..d72caa6df83c0c21c754df184087d6f80c79b338 100644 (file)
@@ -50,6 +50,7 @@ typedef struct uv_check_s uv_check_t;
 typedef struct uv_idle_s uv_idle_t;
 typedef struct uv_async_s uv_async_t;
 typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
+typedef struct uv_process_s uv_process_t;
 /* Request types */
 typedef struct uv_req_s uv_req_t;
 typedef struct uv_shutdown_s uv_shutdown_t;
@@ -76,7 +77,7 @@ typedef void (*uv_read_cb)(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf);
 typedef void (*uv_write_cb)(uv_write_t* req, int status);
 typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
 typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
-typedef void (*uv_connection_cb)(uv_handle_t* server, int status);
+typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
 typedef void (*uv_close_cb)(uv_handle_t* handle);
 typedef void (*uv_timer_cb)(uv_timer_t* handle, int status);
 /* TODO: do these really need a status argument? */
@@ -85,6 +86,7 @@ typedef void (*uv_prepare_cb)(uv_prepare_t* handle, int status);
 typedef void (*uv_check_cb)(uv_check_t* handle, int status);
 typedef void (*uv_idle_cb)(uv_idle_t* handle, int status);
 typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* handle, int status, struct addrinfo* res);
+typedef void (*uv_exit_cb)(uv_process_t*, int exit_status, int term_signal);
 
 
 /* Expand this list if necessary. */
@@ -145,7 +147,8 @@ typedef enum {
   UV_ASYNC,
   UV_ARES_TASK,
   UV_ARES_EVENT,
-  UV_GETADDRINFO
+  UV_GETADDRINFO,
+  UV_PROCESS
 } uv_handle_type;
 
 typedef enum {
@@ -244,6 +247,8 @@ struct uv_stream_s {
   UV_STREAM_FIELDS
 };
 
+int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
+
 /* This call is used in conjunction with uv_listen() to accept incoming
  * connections. Call uv_accept after receiving a uv_connection_cb to accept
  * the connection. Before calling uv_accept use uv_*_init() must be
@@ -254,7 +259,7 @@ struct uv_stream_s {
  * once, it may fail. It is suggested to only call uv_accept once per
  * uv_connection_cb call.
  */
-int uv_accept(uv_handle_t* server, uv_stream_t* client);
+int uv_accept(uv_stream_t* server, uv_stream_t* client);
 
 /* Read data from an incoming stream. The callback will be made several
  * several times until there is no more data to read or uv_read_stop is
@@ -269,6 +274,14 @@ int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
 
 int uv_read_stop(uv_stream_t*);
 
+typedef enum {
+  UV_STDIN = 0,
+  UV_STDOUT,
+  UV_STDERR
+} uv_std_type;
+
+uv_stream_t* uv_std_handle(uv_std_type type);
+
 /*
  * Write data to stream. Buffers are written in order. Example:
  *
@@ -332,8 +345,6 @@ int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle,
 int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle,
     struct sockaddr_in6 address, uv_connect_cb cb);
 
-int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
-
 int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
 
 
@@ -350,8 +361,6 @@ int uv_pipe_init(uv_pipe_t* handle);
 
 int uv_pipe_bind(uv_pipe_t* handle, const char* name);
 
-int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb);
-
 int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
     const char* name, uv_connect_cb cb);
 
@@ -489,6 +498,41 @@ struct uv_getaddrinfo_s {
                     const char* service,
                     const struct addrinfo* hints);
 
+/*
+ * Child process. Subclass of uv_handle_t.
+ */
+typedef struct uv_process_options_s {
+  uv_exit_cb exit_cb;
+  const char* file;
+  char** args;
+  char** env;
+  char* cwd;
+  /*
+   * The user should supply pointers to uninitialized uv_pipe_t structs for
+   * stdio. They will be initialized by uv_spawn. The user is reponsible for
+   * calling uv_close on them.
+   */
+  uv_pipe_t* stdin_stream;
+  uv_pipe_t* stdout_stream;
+  uv_pipe_t* stderr_stream;
+} uv_process_options_t;
+
+struct uv_process_s {
+  UV_HANDLE_FIELDS
+  uv_exit_cb exit_cb;
+  int pid;
+  UV_PROCESS_PRIVATE_FIELDS
+};
+
+/* Initializes uv_process_t and starts the process. */
+int uv_spawn(uv_process_t*, uv_process_options_t options);
+
+/*
+ * Kills the process with the specified signal. The user must still
+ * call uv_close on the process.
+ */
+int uv_process_kill(uv_process_t*, int signum);
+
 
 /*
  * Most functions return boolean: 0 for success and -1 for failure.
@@ -570,6 +614,7 @@ typedef struct {
   uint64_t idle_init;
   uint64_t async_init;
   uint64_t timer_init;
+  uint64_t process_init;
 } uv_counters_t;
 
 uv_counters_t* uv_counters();
index fbfca789412b01a321c216028c3494024d6cf78c..8a9975d6d85e8ac347b539cf84d235a9e58c95e9 100644 (file)
     <ClCompile Include="..\src\win\loop-watcher.c" />
     <ClCompile Include="..\src\win\pipe.c" />
     <ClCompile Include="..\src\win\req.c" />
+    <ClCompile Include="..\src\win\stdio.c" />
     <ClCompile Include="..\src\win\stream.c" />
     <ClCompile Include="..\src\win\tcp.c" />
     <ClCompile Include="..\src\win\timer.c" />
index be52582f74cb5cc5e253fbaf5e966d388d5266e7..8d1c942029784211c591c59ca4705593092487eb 100644 (file)
 #endif
 
 
+# ifdef __APPLE__
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+# else
+extern char **environ;
+# endif
+
+
 static uv_err_t last_err;
 
 struct uv_ares_data_s {
@@ -72,6 +80,8 @@ static int uv__stream_open(uv_stream_t*, int fd);
 static void uv__finish_close(uv_handle_t* handle);
 static uv_err_t uv_err_new(uv_handle_t* handle, int sys_error);
 
+static int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
+static int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
 static uv_write_t* uv__write(uv_stream_t* stream);
 static void uv__read(uv_stream_t* stream);
 static void uv__stream_connect(uv_stream_t*);
@@ -192,6 +202,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
   uv_pipe_t* pipe;
   uv_async_t* async;
   uv_timer_t* timer;
+  uv_process_t* process;
 
   handle->close_cb = close_cb;
 
@@ -244,6 +255,11 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
       ev_io_stop(EV_DEFAULT_ &pipe->write_watcher);
       break;
 
+    case UV_PROCESS:
+      process = (uv_process_t*)handle;
+      ev_child_stop(EV_DEFAULT_UC_ &process->child_watcher);
+      break;
+
     default:
       assert(0);
   }
@@ -314,7 +330,8 @@ int uv_tcp_init(uv_tcp_t* tcp) {
 }
 
 
-int uv__bind(uv_tcp_t* tcp, int domain, struct sockaddr* addr, int addrsize) {
+static int uv__bind(uv_tcp_t* tcp, int domain, struct sockaddr* addr,
+    int addrsize) {
   int saved_errno;
   int status;
   int fd;
@@ -360,7 +377,8 @@ int uv_tcp_bind(uv_tcp_t* tcp, struct sockaddr_in addr) {
     return -1;
   }
 
-  return uv__bind(tcp, AF_INET, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));
+  return uv__bind(tcp, AF_INET, (struct sockaddr*)&addr,
+      sizeof(struct sockaddr_in));
 }
 
 
@@ -370,7 +388,8 @@ int uv_tcp_bind6(uv_tcp_t* tcp, struct sockaddr_in6 addr) {
     return -1;
   }
 
-  return uv__bind(tcp, AF_INET6, (struct sockaddr*)&addr, sizeof(struct sockaddr_in6));
+  return uv__bind(tcp, AF_INET6, (struct sockaddr*)&addr,
+      sizeof(struct sockaddr_in6));
 }
 
 
@@ -429,12 +448,12 @@ void uv__server_io(EV_P_ ev_io* watcher, int revents) {
         return;
       } else {
         uv_err_new((uv_handle_t*)stream, errno);
-        stream->connection_cb((uv_handle_t*)stream, -1);
+        stream->connection_cb((uv_stream_t*)stream, -1);
       }
 
     } else {
       stream->accepted_fd = fd;
-      stream->connection_cb((uv_handle_t*)stream, 0);
+      stream->connection_cb((uv_stream_t*)stream, 0);
       if (stream->accepted_fd >= 0) {
         /* The user hasn't yet accepted called uv_accept() */
         ev_io_stop(EV_DEFAULT_ &stream->read_watcher);
@@ -445,7 +464,7 @@ void uv__server_io(EV_P_ ev_io* watcher, int revents) {
 }
 
 
-int uv_accept(uv_handle_t* server, uv_stream_t* client) {
+int uv_accept(uv_stream_t* server, uv_stream_t* client) {
   uv_stream_t* streamServer;
   uv_stream_t* streamClient;
   int saved_errno;
@@ -458,7 +477,7 @@ int uv_accept(uv_handle_t* server, uv_stream_t* client) {
   streamClient = (uv_stream_t*)client;
 
   if (streamServer->accepted_fd < 0) {
-    uv_err_new(server, EAGAIN);
+    uv_err_new((uv_handle_t*)server, EAGAIN);
     goto out;
   }
 
@@ -479,7 +498,20 @@ out:
 }
 
 
-int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
+int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
+  switch (stream->type) {
+    case UV_TCP:
+      return uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
+    case UV_NAMED_PIPE:
+      return uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
+    default:
+      assert(0);
+      return -1;
+  }
+}
+
+
+static int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
   int r;
   int fd;
 
@@ -565,6 +597,10 @@ void uv__finish_close(uv_handle_t* handle) {
       break;
     }
 
+    case UV_PROCESS:
+      assert(!ev_is_active(&((uv_process_t*)handle)->child_watcher));
+      break;
+
     default:
       assert(0);
       break;
@@ -1544,7 +1580,7 @@ int64_t uv_timer_get_repeat(uv_timer_t* timer) {
 
 
 /*
- * This is called once per second by ares_data.timer. It is used to 
+ * This is called once per second by ares_data.timer. It is used to
  * constantly callback into c-ares for possibly processing timeouts.
  */
 static void uv__ares_timeout(EV_P_ struct ev_timer* watcher, int revents) {
@@ -1870,7 +1906,7 @@ out:
 }
 
 
-int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb) {
+static int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
   int saved_errno;
   int status;
 
@@ -1883,7 +1919,7 @@ int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb) {
   }
   assert(handle->fd >= 0);
 
-  if ((status = listen(handle->fd, SOMAXCONN)) == -1) {
+  if ((status = listen(handle->fd, backlog)) == -1) {
     uv_err_new((uv_handle_t*)handle, errno);
   } else {
     handle->connection_cb = cb;
@@ -1984,7 +2020,7 @@ static void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) {
     }
   } else {
     pipe->accepted_fd = sockfd;
-    pipe->connection_cb((uv_handle_t*)pipe, 0);
+    pipe->connection_cb((uv_stream_t*)pipe, 0);
     if (pipe->accepted_fd == sockfd) {
       /* The user hasn't yet accepted called uv_accept() */
       ev_io_stop(EV_DEFAULT_ &pipe->read_watcher);
@@ -2114,3 +2150,161 @@ size_t uv__strlcpy(char* dst, const char* src, size_t size) {
 
   return src - org;
 }
+
+
+uv_stream_t* uv_std_handle(uv_std_type type) {
+  assert(0 && "implement me");
+}
+
+
+static void uv__chld(EV_P_ ev_child* watcher, int revents) {
+  int status = watcher->rstatus;
+  int exit_status = 0;
+  int term_signal = 0;
+  uv_process_t *process = watcher->data;
+
+  assert(&process->child_watcher == watcher);
+  assert(revents & EV_CHILD);
+
+  ev_child_stop(EV_A_ &process->child_watcher);
+
+  if (WIFEXITED(status)) {
+    exit_status = WEXITSTATUS(status);
+  }
+
+  if (WIFSIGNALED(status)) {
+    term_signal = WTERMSIG(status);
+  }
+
+  if (process->exit_cb) {
+    process->exit_cb(process, exit_status, term_signal);
+  }
+}
+
+
+int uv_spawn(uv_process_t* process, uv_process_options_t options) {
+  /*
+   * Save environ in the case that we get it clobbered
+   * by the child process.
+   */
+  char** save_our_env = environ;
+  int stdin_pipe[2] = { -1, -1 };
+  int stdout_pipe[2] = { -1, -1 };
+  int stderr_pipe[2] = { -1, -1 };
+  pid_t pid;
+
+  uv__handle_init((uv_handle_t*)process, UV_PROCESS);
+  uv_counters()->process_init++;
+
+  process->exit_cb = options.exit_cb;
+
+
+  if (options.stdin_stream && pipe(stdin_pipe) < 0) {
+    goto error;
+  }
+
+  if (options.stdout_stream && pipe(stdout_pipe) < 0) {
+    goto error;
+  }
+
+  if (options.stderr_stream && pipe(stderr_pipe) < 0) {
+    goto error;
+  }
+
+  pid = fork();
+
+  if (pid == 0) {
+    if (stdin_pipe[0] >= 0) {
+      close(stdin_pipe[1]);
+      dup2(stdin_pipe[0],  STDIN_FILENO);
+    }
+
+    if (stdout_pipe[1] >= 0) {
+      close(stdout_pipe[0]);
+      dup2(stdout_pipe[1], STDOUT_FILENO);
+    }
+
+    if (stderr_pipe[1] >= 0) {
+      close(stderr_pipe[0]);
+      dup2(stderr_pipe[1], STDERR_FILENO);
+    }
+
+    if (options.cwd && chdir(options.cwd)) {
+      perror("chdir()");
+      _exit(127);
+    }
+
+    environ = options.env;
+
+    execvp(options.file, options.args);
+    perror("execvp()");
+    _exit(127);
+    /* Execution never reaches here. */
+  } else if (pid == -1) {
+    /* Restore environment. */
+    environ = save_our_env;
+    goto error;
+  }
+
+  /* Parent. */
+
+  /* Restore environment. */
+  environ = save_our_env;
+
+  process->pid = pid;
+
+  ev_child_init(&process->child_watcher, uv__chld, pid, 0);
+  ev_child_start(EV_DEFAULT_UC_ &process->child_watcher);
+  process->child_watcher.data = process;
+
+  if (stdin_pipe[1] >= 0) {
+    assert(options.stdin_stream);
+    assert(stdin_pipe[0] >= 0);
+    close(stdin_pipe[0]);
+    uv__nonblock(stdin_pipe[1], 1);
+    uv_pipe_init(options.stdin_stream);
+    uv__stream_open((uv_stream_t*)options.stdin_stream, stdin_pipe[1]);
+  }
+
+  if (stdout_pipe[0] >= 0) {
+    assert(options.stdout_stream);
+    assert(stdout_pipe[1] >= 0);
+    close(stdout_pipe[1]);
+    uv__nonblock(stdout_pipe[0], 1);
+    uv_pipe_init(options.stdout_stream);
+    uv__stream_open((uv_stream_t*)options.stdout_stream, stdout_pipe[0]);
+  }
+
+  if (stderr_pipe[0] >= 0) {
+    assert(options.stderr_stream);
+    assert(stderr_pipe[1] >= 0);
+    close(stderr_pipe[1]);
+    uv__nonblock(stderr_pipe[0], 1);
+    uv_pipe_init(options.stderr_stream);
+    uv__stream_open((uv_stream_t*)options.stderr_stream, stderr_pipe[0]);
+  }
+
+  return 0;
+
+error:
+  uv_err_new((uv_handle_t*)process, errno);
+  close(stdin_pipe[0]);
+  close(stdin_pipe[1]);
+  close(stdout_pipe[0]);
+  close(stdout_pipe[1]);
+  close(stderr_pipe[0]);
+  close(stderr_pipe[1]);
+  return -1;
+}
+
+
+int uv_process_kill(uv_process_t* process, int signum) {
+  int r = kill(process->pid, signum);
+
+  if (r) {
+    uv_err_new((uv_handle_t*)process, errno);
+    return -1;
+  } else {
+    return 0;
+  }
+}
index 87b9c37b9858de10ff061bfdb60778cb558a1e85..efb05f85fe96947b8ee1f6c902cefe314dbb79bb 100644 (file)
@@ -102,6 +102,8 @@ extern uv_loop_t uv_main_loop_;
 #define UV_HANDLE_IPV6             0x2000
 #define UV_HANDLE_PIPESERVER       0x4000
 #define UV_HANDLE_READ_PENDING     0x8000
+#define UV_HANDLE_GIVEN_OS_HANDLE  0x10000
+#define UV_HANDLE_UV_ALLOCED       0x20000
 
 void uv_want_endgame(uv_handle_t* handle);
 void uv_process_endgames();
@@ -144,6 +146,7 @@ void uv_winsock_startup();
 
 void uv_tcp_endgame(uv_tcp_t* handle);
 
+int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
 int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
 int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
     uv_read_cb read_cb);
@@ -159,9 +162,11 @@ void uv_process_tcp_connect_req(uv_tcp_t* handle, uv_connect_t* req);
 /*
  * Pipes
  */
+int uv_pipe_init_with_handle(uv_pipe_t* handle, HANDLE pipeHandle);
 void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err);
 void uv_pipe_endgame(uv_pipe_t* handle);
 
+int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
 int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client);
 int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
     uv_read_cb read_cb);
index fe47b393c6e520dd44f05c08bcaae5ad95034cd1..7c98ab0effa71255741ff3b156ac053a6aa93a3f 100644 (file)
@@ -46,6 +46,23 @@ int uv_pipe_init(uv_pipe_t* handle) {
 }
 
 
+int uv_pipe_init_with_handle(uv_pipe_t* handle, HANDLE pipeHandle) {
+  int err = uv_pipe_init(handle);
+
+  if (!err) {
+    /* 
+     * At this point we don't know whether the pipe will be used as a client
+     * or a server.  So, we assume that it will be a client until 
+     * uv_listen is called.
+     */
+    handle->handle = pipeHandle;
+    handle->flags |= UV_HANDLE_GIVEN_OS_HANDLE;
+  }
+
+  return err;
+}
+
+
 static int uv_set_pipe_handle(uv_pipe_t* handle, HANDLE pipeHandle) {
   DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
 
@@ -91,6 +108,10 @@ void uv_pipe_endgame(uv_pipe_t* handle) {
       handle->close_cb((uv_handle_t*)handle);
     }
 
+    if (handle->flags & UV_HANDLE_UV_ALLOCED) {
+      free(handle);
+    }
+
     uv_unref();
   }
 }
@@ -407,7 +428,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) {
   req->next_pending = NULL;
   req->pipeHandle = INVALID_HANDLE_VALUE;
 
-  if (!(server->flags & UV_HANDLE_CLOSING)) {
+  if (!(server->flags & UV_HANDLE_CLOSING) &&
+      !(server->flags & UV_HANDLE_GIVEN_OS_HANDLE)) {
     uv_pipe_queue_accept(server, req, FALSE);
   }
 
@@ -416,15 +438,18 @@ int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) {
 
 
 /* Starts listening for connections for the given pipe. */
-int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb) {
+int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
   int i, errno;
+  uv_pipe_accept_t* req;
+  HANDLE pipeHandle;
 
   if (handle->flags & UV_HANDLE_BIND_ERROR) {
     LOOP->last_error = handle->error;
     return -1;
   }
 
-  if (!(handle->flags & UV_HANDLE_BOUND)) {
+  if (!(handle->flags & UV_HANDLE_BOUND) && 
+      !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) {
     uv_set_error(UV_ENOTCONN, 0);
     return -1;
   }
@@ -435,7 +460,8 @@ int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb) {
     return -1;
   }
 
-  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
+  if (!(handle->flags & UV_HANDLE_PIPESERVER) && 
+      !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) {
     uv_set_error(UV_ENOTSUP, 0);
     return -1;
   }
@@ -443,11 +469,30 @@ int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb) {
   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);
+  if (handle->flags & UV_HANDLE_GIVEN_OS_HANDLE) {
+    handle->flags |= UV_HANDLE_PIPESERVER;
+    pipeHandle = handle->handle;
+    assert(pipeHandle != INVALID_HANDLE_VALUE);
+    req = &handle->accept_reqs[0];
+    uv_req_init((uv_req_t*) req);
+    req->pipeHandle = pipeHandle;
+    req->type = UV_ACCEPT;
+    req->data = handle;
+    req->next_pending = NULL;
 
-  for (i = 0; i < COUNTOF(handle->accept_reqs); i++) {
-    uv_pipe_queue_accept(handle, &handle->accept_reqs[i], i == 0);
+    if (uv_set_pipe_handle(handle, pipeHandle)) {
+      uv_set_sys_error(GetLastError());
+      return -1;
+    }
+
+    uv_pipe_queue_accept(handle, req, TRUE);
+  } else {
+    /* 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], i == 0);
+    }
   }
 
   return 0;
@@ -678,14 +723,15 @@ void uv_process_pipe_accept_req(uv_pipe_t* handle, uv_req_t* raw_req) {
     handle->pending_accepts = req;
 
     if (handle->connection_cb) {
-      handle->connection_cb((uv_handle_t*)handle, 0);
+      handle->connection_cb((uv_stream_t*)handle, 0);
     }
   } else {
     if (req->pipeHandle != INVALID_HANDLE_VALUE) {
       CloseHandle(req->pipeHandle);
       req->pipeHandle = INVALID_HANDLE_VALUE;
     }
-    if (!(handle->flags & UV_HANDLE_CLOSING)) {
+    if (!(handle->flags & UV_HANDLE_CLOSING) &&
+        !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) {
       uv_pipe_queue_accept(handle, req, FALSE);
     }
   }
diff --git a/deps/uv/src/win/stdio.c b/deps/uv/src/win/stdio.c
new file mode 100644 (file)
index 0000000..0333133
--- /dev/null
@@ -0,0 +1,75 @@
+/* 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 <assert.h>
+#include <string.h>
+
+#include "uv.h"
+#include "../uv-common.h"
+#include "internal.h"
+
+
+static uv_pipe_t* uv_make_pipe_for_std_handle(HANDLE handle) {
+  uv_pipe_t* pipe = NULL;
+
+  pipe = (uv_pipe_t*)malloc(sizeof(uv_pipe_t));
+  if (!pipe) {
+    uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+  }
+
+  if (uv_pipe_init_with_handle(pipe, handle)) {
+    free(pipe);
+    return NULL;
+  }
+
+  pipe->flags |= UV_HANDLE_UV_ALLOCED;
+  return pipe;
+}
+
+
+uv_stream_t* uv_std_handle(uv_std_type type) {
+  HANDLE handle;
+
+  switch (type) {
+    case UV_STDIN:
+      handle = GetStdHandle(STD_INPUT_HANDLE);
+      if (handle == INVALID_HANDLE_VALUE) {
+        return NULL;
+      }
+
+      /* Assume only named pipes for now. */
+      return (uv_stream_t*)uv_make_pipe_for_std_handle(handle);
+      break;
+
+    case UV_STDOUT:
+      return NULL;
+      break;
+
+    case UV_STDERR:
+      return NULL;
+      break;
+
+    default:
+      assert(0);
+      uv_set_error(UV_EINVAL, 0);
+      return NULL;
+  }
+}
index acd67a0c58c494027b3385d90ed6395f851ad373..fcd88b8d6768ccb1daf131f98a30db0567651033 100644 (file)
@@ -48,27 +48,44 @@ void uv_connection_init(uv_stream_t* handle) {
 }
 
 
-int uv_accept(uv_handle_t* server, uv_stream_t* client) {
+int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
+  switch (stream->type) {
+    case UV_TCP:
+      return uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
+    case UV_NAMED_PIPE:
+      return uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
+    default:
+      assert(0);
+      return -1;
+  }
+}
+
+
+int uv_accept(uv_stream_t* server, uv_stream_t* client) {
   assert(client->type == server->type);
 
-  if (server->type == UV_TCP) {
-    return uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client);
-  } else if (server->type == UV_NAMED_PIPE) {
-    return uv_pipe_accept((uv_pipe_t*)server, (uv_pipe_t*)client);
+  switch (server->type) {
+    case UV_TCP:
+      return uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client);
+    case UV_NAMED_PIPE:
+      return uv_pipe_accept((uv_pipe_t*)server, (uv_pipe_t*)client);
+    default:
+      assert(0);
+      return -1;
   }
-
-  return -1;
 }
 
 
 int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb) {
-  if (handle->type == UV_TCP) {
-    return uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb);
-  } else if (handle->type == UV_NAMED_PIPE) {
-    return uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb);
+  switch (handle->type) {
+    case UV_TCP:
+      return uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb);
+    case UV_NAMED_PIPE:
+      return uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb);
+    default:
+      assert(0);
+      return -1;
   }
-
-  return -1;
 }
 
 
@@ -81,14 +98,16 @@ int uv_read_stop(uv_stream_t* handle) {
 
 int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt,
     uv_write_cb cb) {
-  if (handle->type == UV_TCP) {
-    return uv_tcp_write(req, (uv_tcp_t*) handle, bufs, bufcnt, cb);
-  } else if (handle->type == UV_NAMED_PIPE) {
-    return uv_pipe_write(req, (uv_pipe_t*) handle, bufs, bufcnt, cb);
+  switch (handle->type) {
+    case UV_TCP:
+      return uv_tcp_write(req, (uv_tcp_t*) handle, bufs, bufcnt, cb);
+    case UV_NAMED_PIPE:
+      return uv_pipe_write(req, (uv_pipe_t*) handle, bufs, bufcnt, cb);
+    default:
+      assert(0);
+      uv_set_sys_error(WSAEINVAL);
+      return -1;
   }
-
-  uv_set_sys_error(WSAEINVAL);
-  return -1;
 }
 
 
index ace5353d20cd36002c2bc5c0a17ebb8939ab0468..c8d252c14f24b3682fc7984329772a7be313e99f 100644 (file)
@@ -842,7 +842,7 @@ void uv_process_tcp_accept_req(uv_tcp_t* handle, uv_req_t* req) {
       handle->flags &= ~UV_HANDLE_LISTENING;
       if (handle->connection_cb) {
         LOOP->last_error = req->error;
-        handle->connection_cb((uv_handle_t*)handle, -1);
+        handle->connection_cb((uv_stream_t*)handle, -1);
       }
     }
   } else if (req->error.code == UV_OK &&
@@ -853,7 +853,7 @@ void uv_process_tcp_accept_req(uv_tcp_t* handle, uv_req_t* req) {
                   sizeof(handle->socket)) == 0) {
     /* Accept and SO_UPDATE_ACCEPT_CONTEXT were successful. */
     if (handle->connection_cb) {
-      handle->connection_cb((uv_handle_t*)handle, 0);
+      handle->connection_cb((uv_stream_t*)handle, 0);
     }
   } else {
     /* Error related to accepted socket is ignored because the server */
index 1732e84ff540a8a1d36867c71756c9fcc37e91d5..4e7f1d7ace6d25e3b5df92aa38684301e1aa4233 100644 (file)
@@ -47,7 +47,7 @@ static void buf_free(uv_buf_t uv_buf_t);
 
 static uv_tcp_t tcpServer;
 static uv_pipe_t pipeServer;
-static uv_handle_t* server;
+static uv_stream_t* server;
 static struct sockaddr_in listen_addr;
 static struct sockaddr_in connect_addr;
 
@@ -143,7 +143,7 @@ void read_sockets_close_cb(uv_handle_t* handle) {
    */
   if (uv_now() - start_time > 1000 && read_sockets == 0) {
     read_show_stats();
-    uv_close(server, NULL);
+    uv_close((uv_handle_t*)server, NULL);
   }
 }
 
@@ -266,7 +266,7 @@ static void maybe_connect_some() {
 }
 
 
-static void connection_cb(uv_handle_t* s, int status) {
+static void connection_cb(uv_stream_t* s, int status) {
   uv_stream_t* stream;
   int r;
 
@@ -373,12 +373,12 @@ HELPER_IMPL(tcp_pump_server) {
   listen_addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
 
   /* Server */
-  server = (uv_handle_t*)&tcpServer;
+  server = (uv_stream_t*)&tcpServer;
   r = uv_tcp_init(&tcpServer);
   ASSERT(r == 0);
   r = uv_tcp_bind(&tcpServer, listen_addr);
   ASSERT(r == 0);
-  r = uv_tcp_listen(&tcpServer, MAX_WRITE_HANDLES, connection_cb);
+  r = uv_listen((uv_stream_t*)&tcpServer, MAX_WRITE_HANDLES, connection_cb);
   ASSERT(r == 0);
 
   uv_run();
@@ -394,12 +394,12 @@ HELPER_IMPL(pipe_pump_server) {
   uv_init();
 
   /* Server */
-  server = (uv_handle_t*)&pipeServer;
+  server = (uv_stream_t*)&pipeServer;
   r = uv_pipe_init(&pipeServer);
   ASSERT(r == 0);
   r = uv_pipe_bind(&pipeServer, TEST_PIPENAME);
   ASSERT(r == 0);
-  r = uv_pipe_listen(&pipeServer, connection_cb);
+  r = uv_listen((uv_stream_t*)&pipeServer, MAX_WRITE_HANDLES, connection_cb);
   ASSERT(r == 0);
 
   uv_run();
index 1c6b78fd331f2bb5dbdad8b6fd00c119bab41748..f1593528ede8d90ad53f40855c08a3cbaa5d7c48 100644 (file)
@@ -55,7 +55,7 @@ static void after_write(uv_write_t* req, int status);
 static void after_read(uv_stream_t*, ssize_t nread, uv_buf_t buf);
 static void on_close(uv_handle_t* peer);
 static void on_server_close(uv_handle_t* handle);
-static void on_connection(uv_handle_t*, int status);
+static void on_connection(uv_stream_t*, int status);
 
 #define WRITE_BUF_LEN   (64*1024)
 #define DNSREC_LEN      (4)
@@ -255,7 +255,7 @@ static uv_buf_t buf_alloc(uv_stream_t* handle, size_t suggested_size) {
 }
 
 
-static void on_connection(uv_handle_t* server, int status) {
+static void on_connection(uv_stream_t* server, int status) {
   dnshandle* handle;
   int r;
 
@@ -302,7 +302,7 @@ static int dns_start(int port) {
     return 1;
   }
 
-  r = uv_tcp_listen(&server, 128, on_connection);
+  r = uv_listen((uv_stream_t*)&server, 128, on_connection);
   if (r) {
     /* TODO: Error codes */
     fprintf(stderr, "Listen error\n");
index 992c88bb2d1cde0ec6f5833de1bfb77f5ba74fbf..add2383983f2aef6b317ec2b9bc37322a39d52b2 100644 (file)
@@ -39,7 +39,7 @@ static void after_write(uv_write_t* req, int status);
 static void after_read(uv_stream_t*, ssize_t nread, uv_buf_t buf);
 static void on_close(uv_handle_t* peer);
 static void on_server_close(uv_handle_t* handle);
-static void on_connection(uv_handle_t*, int status);
+static void on_connection(uv_stream_t*, int status);
 
 
 static void after_write(uv_write_t* req, int status) {
@@ -123,7 +123,7 @@ static uv_buf_t echo_alloc(uv_stream_t* handle, size_t suggested_size) {
 }
 
 
-static void on_connection(uv_handle_t* server, int status) {
+static void on_connection(uv_stream_t* server, int status) {
   uv_stream_t* stream;
   int r;
 
@@ -187,7 +187,7 @@ static int tcp4_echo_start(int port) {
     return 1;
   }
 
-  r = uv_tcp_listen(&tcpServer, 128, on_connection);
+  r = uv_listen((uv_stream_t*)&tcpServer, 128, on_connection);
   if (r) {
     /* TODO: Error codes */
     fprintf(stderr, "Listen error\n");
@@ -220,7 +220,7 @@ static int tcp6_echo_start(int port) {
     return 0;
   }
 
-  r = uv_tcp_listen(&tcpServer, 128, on_connection);
+  r = uv_listen((uv_stream_t*)&tcpServer, 128, on_connection);
   if (r) {
     /* TODO: Error codes */
     fprintf(stderr, "Listen error\n");
@@ -249,7 +249,7 @@ static int pipe_echo_start(char* pipeName) {
     return 1;
   }
 
-  r = uv_pipe_listen(&pipeServer, on_connection);
+  r = uv_listen((uv_stream_t*)&pipeServer, SOMAXCONN, on_connection);
   if (r) {
     fprintf(stderr, "uv_pipe_listen: %s\n", uv_strerror(uv_last_error()));
     return 1;
index 7ae6c6c7cb07108a1a4775d4a801ad6b0692ac7f..c4a70dc93e70753f5a554d31a8352ec52da28b19 100644 (file)
 
 
 int main(int argc, char **argv) {
+  int i;
+
   platform_init(argc, argv);
 
   switch (argc) {
   case 1: return run_tests(TEST_TIMEOUT, 0);
-  case 2: return run_test(argv[1], TEST_TIMEOUT, 0);
+  case 2: {
+    if (strcmp(argv[1], "spawn_helper1") == 0) {
+      return 1;
+    }
+
+    if (strcmp(argv[1], "spawn_helper2") == 0) {
+      printf("hello world\n");
+      return 1;
+    }
+
+    return run_test(argv[1], TEST_TIMEOUT, 0);
+  }
   case 3: return run_test_part(argv[1], argv[2]);
   default:
     LOGF("Too many arguments.\n");
index 8e3dfc1461a13508754c3020cece9dea5d869fdd..10f041b2cdc7fd64c7a6c7ddf8f29dacf30612c4 100644 (file)
@@ -63,7 +63,7 @@ static void do_accept(uv_timer_t* timer_handle, int status) {
   tcpcnt = uv_counters()->tcp_init;
 
   server = (uv_tcp_t*)timer_handle->data;
-  r = uv_accept((uv_handle_t*)server, (uv_stream_t*)accepted_handle);
+  r = uv_accept((uv_stream_t*)server, (uv_stream_t*)accepted_handle);
   ASSERT(r == 0);
 
   ASSERT(uv_counters()->tcp_init == tcpcnt);
@@ -83,7 +83,7 @@ static void do_accept(uv_timer_t* timer_handle, int status) {
 }
 
 
-static void connection_cb(uv_handle_t* tcp, int status) {
+static void connection_cb(uv_stream_t* tcp, int status) {
   int r;
   uv_timer_t* timer_handle;
 
@@ -120,7 +120,7 @@ static void start_server() {
   r = uv_tcp_bind(server, addr);
   ASSERT(r == 0);
 
-  r = uv_tcp_listen(server, 128, connection_cb);
+  r = uv_listen((uv_stream_t*)server, 128, connection_cb);
   ASSERT(r == 0);
 }
 
index 6e4f6436618dd4ba18bf0735ebe8ef4827a8c789..8b783ec568b1b55336aceed917efcea3cd7affa4 100644 (file)
@@ -67,7 +67,7 @@ static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
 }
 
 
-static void on_connection(uv_handle_t* server, int status) {
+static void on_connection(uv_stream_t* server, int status) {
   struct sockaddr sockname;
   int namelen = sizeof(sockname);
   uv_handle_t* handle;
@@ -141,7 +141,7 @@ static int tcp_listener(int port) {
     return 1;
   }
 
-  r = uv_tcp_listen(&tcpServer, 128, on_connection);
+  r = uv_listen((uv_stream_t*)&tcpServer, 128, on_connection);
   if (r) {
     fprintf(stderr, "Listen error\n");
     return 1;
index de9f1d3addb4145ea85c87b59bde3c37d2bef07f..99d59e556f8b6d92ee84709549efc2dde571d7d9 100644 (file)
@@ -63,6 +63,8 @@ TEST_DECLARE   (gethostbyname)
 TEST_DECLARE   (getsockname)
 TEST_DECLARE   (fail_always)
 TEST_DECLARE   (pass_always)
+TEST_DECLARE   (spawn_exit_code)
+TEST_DECLARE   (spawn_stdout)
 HELPER_DECLARE (tcp4_echo_server)
 HELPER_DECLARE (tcp6_echo_server)
 HELPER_DECLARE (pipe_echo_server)
@@ -140,6 +142,9 @@ TASK_LIST_START
 
   TEST_ENTRY  (getsockname)
 
+  TEST_ENTRY  (spawn_exit_code)
+  TEST_ENTRY  (spawn_stdout)
+
 #if 0
   /* These are for testing the test runner. */
   TEST_ENTRY  (fail_always)
index 6faccbe202661d7757bfad60ba72811e0a74a488..69aaaa20cd497cd167b7006824a67a018fde0520 100644 (file)
@@ -59,9 +59,9 @@ TEST_IMPL(pipe_bind_error_addrinuse) {
 
   ASSERT(uv_last_error().code == UV_EADDRINUSE);
 
-  r = uv_pipe_listen(&server1, NULL);
+  r = uv_listen((uv_stream_t*)&server1, SOMAXCONN, NULL);
   ASSERT(r == 0);
-  r = uv_pipe_listen(&server2, NULL);
+  r = uv_listen((uv_stream_t*)&server2, SOMAXCONN, NULL);
   ASSERT(r == -1);
 
   ASSERT(uv_last_error().code == UV_EADDRINUSE);
@@ -133,7 +133,7 @@ TEST_IMPL(pipe_listen_without_bind) {
 
   r = uv_pipe_init(&server);
   ASSERT(r == 0);
-  r = uv_pipe_listen(&server, NULL);
+  r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
   ASSERT(r == -1);
 
   ASSERT(uv_last_error().code == UV_ENOTCONN);
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
new file mode 100644 (file)
index 0000000..9449af7
--- /dev/null
@@ -0,0 +1,134 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+static int close_cb_called;
+static int exit_cb_called;
+static uv_process_t process;
+static uv_process_options_t options = { 0 };
+static char exepath[1024];
+static size_t exepath_size = 1024;
+static char* args[3];
+
+#define OUTPUT_SIZE 1024
+static char output[OUTPUT_SIZE];
+static int output_used;
+
+
+static void close_cb(uv_handle_t* handle) {
+  printf("close_cb\n");
+  close_cb_called++;
+}
+
+
+static void exit_cb(uv_process_t* process, int exit_status, int term_signal) {
+  printf("exit_cb\n");
+  exit_cb_called++;
+  ASSERT(exit_status == 1);
+  ASSERT(term_signal == 0);
+  uv_close((uv_handle_t*)process, close_cb);
+}
+
+
+uv_buf_t on_alloc(uv_stream_t* tcp, size_t suggested_size) {
+  uv_buf_t buf;
+  buf.base = output + output_used;
+  buf.len = OUTPUT_SIZE - output_used;
+  return buf;
+}
+
+
+void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
+  uv_err_t err = uv_last_error();
+
+  if (nread > 0) {
+    output_used += nread;
+  } else if (nread < 0) {
+    if (err.code == UV_EOF) {
+      uv_close((uv_handle_t*)tcp, close_cb);
+    }
+  }
+}
+
+
+static void init_process_options(char* test) {
+  /* Note spawn_helper1 defined in test/run-tests.c */
+  int r = uv_exepath(exepath, &exepath_size);
+  ASSERT(r == 0);
+  exepath[exepath_size] = '\0';
+  args[0] = exepath;
+  args[1] = test;
+  args[2] = NULL;
+  options.file = exepath;
+  options.args = args;
+  options.exit_cb = exit_cb;
+}
+
+
+TEST_IMPL(spawn_exit_code) {
+  int r;
+
+  uv_init();
+
+  init_process_options("spawn_helper1");
+
+  r = uv_spawn(&process, options);
+  ASSERT(r == 0);
+
+  r = uv_run();
+  ASSERT(r == 0);
+
+  ASSERT(exit_cb_called == 1);
+  ASSERT(close_cb_called == 1);
+
+  return 0;
+}
+
+
+TEST_IMPL(spawn_stdout) {
+  int r;
+  uv_pipe_t out;
+
+  uv_init();
+
+  init_process_options("spawn_helper2");
+  options.stdout_stream = &out;
+
+  r = uv_spawn(&process, options);
+  ASSERT(r == 0);
+
+  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
+  ASSERT(r == 0);
+
+  r = uv_run();
+  ASSERT(r == 0);
+
+  ASSERT(exit_cb_called == 1);
+  ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
+  ASSERT(strcmp("hello world\n", output) == 0);
+
+  return 0;
+}
+
index 9034438dfb6dca77de6756ecd8eb2892a3b14b75..b466ef8b4fe738787e6b70e5798232dcbd021279 100644 (file)
@@ -51,9 +51,9 @@ TEST_IMPL(tcp_bind_error_addrinuse) {
   r = uv_tcp_bind(&server2, addr);
   ASSERT(r == 0);
 
-  r = uv_tcp_listen(&server1, 128, NULL);
+  r = uv_listen((uv_stream_t*)&server1, 128, NULL);
   ASSERT(r == 0);
-  r = uv_tcp_listen(&server2, 128, NULL);
+  r = uv_listen((uv_stream_t*)&server2, 128, NULL);
   ASSERT(r == -1);
 
   ASSERT(uv_last_error().code == UV_EADDRINUSE);
@@ -197,7 +197,7 @@ TEST_IMPL(tcp_listen_without_bind) {
   uv_init();
   r = uv_tcp_init(&server);
   ASSERT(r == 0);
-  r = uv_tcp_listen(&server, 128, NULL);
+  r = uv_listen((uv_stream_t*)&server, 128, NULL);
   ASSERT(r == 0);
 
   return 0;
index d2127858ee9cec018c3506c21861183a783a3530..cf283fa00061b5f49fd51386b7b618e9e4f76838 100644 (file)
@@ -51,9 +51,9 @@ TEST_IMPL(tcp_bind6_error_addrinuse) {
   r = uv_tcp_bind6(&server2, addr);
   ASSERT(r == 0);
 
-  r = uv_tcp_listen(&server1, 128, NULL);
+  r = uv_listen((uv_stream_t*)&server1, 128, NULL);
   ASSERT(r == 0);
-  r = uv_tcp_listen(&server2, 128, NULL);
+  r = uv_listen((uv_stream_t*)&server2, 128, NULL);
   ASSERT(r == -1);
 
   ASSERT(uv_last_error().code == UV_EADDRINUSE);