summaryrefslogtreecommitdiff
path: root/deps/uv/src/unix/process.c
diff options
context:
space:
mode:
authorFedor Indutny <fedor.indutny@gmail.com>2012-05-28 23:52:34 +0400
committerFedor Indutny <fedor.indutny@gmail.com>2012-05-29 18:26:40 +0400
commit761e0c460a8e9a40cd1126cf0ba354e50e38d6da (patch)
tree314a084790dd95dcea5ea4928321a9d47c3aaa93 /deps/uv/src/unix/process.c
parentfa9aa1c961125f5c5527c7b5e3720eadf84a979f (diff)
downloadandroid-node-v8-761e0c460a8e9a40cd1126cf0ba354e50e38d6da.tar.gz
android-node-v8-761e0c460a8e9a40cd1126cf0ba354e50e38d6da.tar.bz2
android-node-v8-761e0c460a8e9a40cd1126cf0ba354e50e38d6da.zip
deps: upgrade libuv to 7556590
Diffstat (limited to 'deps/uv/src/unix/process.c')
-rw-r--r--deps/uv/src/unix/process.c204
1 files changed, 122 insertions, 82 deletions
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index bccaf17147..2efe896ace 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -138,19 +138,79 @@ int uv__make_pipe(int fds[2], int flags) {
* Used for initializing stdio streams like options.stdin_stream. Returns
* zero on success.
*/
-static int uv__process_init_pipe(uv_pipe_t* handle, int fds[2], int flags) {
- if (handle->type != UV_NAMED_PIPE) {
- errno = EINVAL;
+static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2],
+ int writable) {
+ if (container->flags == UV_IGNORE) {
+ return 0;
+ } else if (container->flags & UV_CREATE_PIPE) {
+ assert(container->data.stream != NULL);
+
+ if (container->data.stream->type != UV_NAMED_PIPE) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ return uv__make_socketpair(fds, 0);
+ } else if (container->flags & UV_RAW_FD) {
+ if (container->data.fd == -1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (writable) {
+ fds[1] = container->data.fd;
+ } else {
+ fds[0] = container->data.fd;
+ }
+
+ return 0;
+ } else {
+ assert(0 && "Unexpected flags");
return -1;
}
+}
+
- if (handle->ipc)
- return uv__make_socketpair(fds, flags);
- else
- return uv__make_pipe(fds, flags);
+static int uv__process_stdio_flags(uv_stdio_container_t* container,
+ int writable) {
+ if (container->data.stream->type == UV_NAMED_PIPE &&
+ ((uv_pipe_t*)container->data.stream)->ipc) {
+ return UV_STREAM_READABLE | UV_STREAM_WRITABLE;
+ } else if (writable) {
+ return UV_STREAM_WRITABLE;
+ } else {
+ return UV_STREAM_READABLE;
+ }
}
+static int uv__process_open_stream(uv_stdio_container_t* container, int fds[2],
+ int writable) {
+ int fd = fds[writable ? 1 : 0];
+ int child_fd = fds[writable ? 0 : 1];
+ int flags;
+
+ /* No need to create stream */
+ if (!(container->flags & UV_CREATE_PIPE) || fd < 0) {
+ return 0;
+ }
+
+ assert(child_fd >= 0);
+ close(child_fd);
+
+ uv__nonblock(fd, 1);
+ flags = uv__process_stdio_flags(container, writable);
+
+ return uv__stream_open((uv_stream_t*)container->data.stream, fd, flags);
+}
+
+
+static void uv__process_close_stream(uv_stdio_container_t* container) {
+ if (!(container->flags & UV_CREATE_PIPE)) return;
+
+ uv__stream_close((uv_stream_t*)container->data.stream);
+}
+
#ifndef SPAWN_WAIT_EXEC
# define SPAWN_WAIT_EXEC 1
#endif
@@ -162,16 +222,21 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
* 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 };
+
+ int* pipes = malloc(2 * options.stdio_count * sizeof(int));
+
#if SPAWN_WAIT_EXEC
int signal_pipe[2] = { -1, -1 };
struct pollfd pfd;
#endif
int status;
pid_t pid;
- int flags;
+ int i;
+
+ if (pipes == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
assert(options.file != NULL);
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
@@ -185,19 +250,17 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
process->exit_cb = options.exit_cb;
- if (options.stdin_stream &&
- uv__process_init_pipe(options.stdin_stream, stdin_pipe, 0)) {
- goto error;
- }
-
- if (options.stdout_stream &&
- uv__process_init_pipe(options.stdout_stream, stdout_pipe, 0)) {
- goto error;
+ /* Init pipe pairs */
+ for (i = 0; i < options.stdio_count; i++) {
+ pipes[i * 2] = -1;
+ pipes[i * 2 + 1] = -1;
}
- if (options.stderr_stream &&
- uv__process_init_pipe(options.stderr_stream, stderr_pipe, 0)) {
- goto error;
+ /* Create socketpairs/pipes, or use raw fd */
+ for (i = 0; i < options.stdio_count; i++) {
+ if (uv__process_init_stdio(&options.stdio[i], pipes + i * 2, i != 0)) {
+ goto error;
+ }
}
/* This pipe is used by the parent to wait until
@@ -237,31 +300,25 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
}
if (pid == 0) {
- if (stdin_pipe[0] >= 0) {
- close(stdin_pipe[1]);
- dup2(stdin_pipe[0], STDIN_FILENO);
- } else {
- /* Reset flags that might be set by Node */
- uv__cloexec(STDIN_FILENO, 0);
- uv__nonblock(STDIN_FILENO, 0);
- }
-
- if (stdout_pipe[1] >= 0) {
- close(stdout_pipe[0]);
- dup2(stdout_pipe[1], STDOUT_FILENO);
- } else {
- /* Reset flags that might be set by Node */
- uv__cloexec(STDOUT_FILENO, 0);
- uv__nonblock(STDOUT_FILENO, 0);
- }
-
- if (stderr_pipe[1] >= 0) {
- close(stderr_pipe[0]);
- dup2(stderr_pipe[1], STDERR_FILENO);
- } else {
- /* Reset flags that might be set by Node */
- uv__cloexec(STDERR_FILENO, 0);
- uv__nonblock(STDERR_FILENO, 0);
+ /* Child */
+
+ /* Dup fds */
+ for (i = 0; i < options.stdio_count; i++) {
+ /*
+ * stdin has swapped ends of pipe
+ * (it's the only one readable stream)
+ */
+ int close_fd = i == 0 ? pipes[i * 2 + 1] : pipes[i * 2];
+ int use_fd = i == 0 ? pipes[i * 2] : pipes[i * 2 + 1];
+
+ if (use_fd >= 0) {
+ close(close_fd);
+ dup2(use_fd, i);
+ } else {
+ /* Reset flags that might be set by Node */
+ uv__cloexec(i, 0);
+ uv__nonblock(i, 0);
+ }
}
if (options.cwd && chdir(options.cwd)) {
@@ -313,49 +370,32 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
ev_child_start(process->loop->ev, &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);
- flags = UV_STREAM_WRITABLE |
- (options.stdin_stream->ipc ? UV_STREAM_READABLE : 0);
- uv__stream_open((uv_stream_t*)options.stdin_stream, stdin_pipe[1],
- flags);
- }
+ for (i = 0; i < options.stdio_count; i++) {
+ if (uv__process_open_stream(&options.stdio[i], pipes + i * 2, i == 0)) {
+ int j;
+ /* Close all opened streams */
+ for (j = 0; j < i; j++) {
+ uv__process_close_stream(&options.stdio[j]);
+ }
- if (stdout_pipe[0] >= 0) {
- assert(options.stdout_stream);
- assert(stdout_pipe[1] >= 0);
- close(stdout_pipe[1]);
- uv__nonblock(stdout_pipe[0], 1);
- flags = UV_STREAM_READABLE |
- (options.stdout_stream->ipc ? UV_STREAM_WRITABLE : 0);
- uv__stream_open((uv_stream_t*)options.stdout_stream, stdout_pipe[0],
- flags);
+ goto error;
+ }
}
- if (stderr_pipe[0] >= 0) {
- assert(options.stderr_stream);
- assert(stderr_pipe[1] >= 0);
- close(stderr_pipe[1]);
- uv__nonblock(stderr_pipe[0], 1);
- flags = UV_STREAM_READABLE |
- (options.stderr_stream->ipc ? UV_STREAM_WRITABLE : 0);
- uv__stream_open((uv_stream_t*)options.stderr_stream, stderr_pipe[0],
- flags);
- }
+ free(pipes);
return 0;
error:
uv__set_sys_error(process->loop, 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]);
+
+ for (i = 0; i < options.stdio_count; i++) {
+ close(pipes[i * 2]);
+ close(pipes[i * 2 + 1]);
+ }
+
+ free(pipes);
+
return -1;
}