From f5b5127db0f3677b7c8e71df5cbc197369615660 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 31 May 2012 17:50:28 +0400 Subject: [PATCH] change spawn() api to allow using existing streams for stdio This commit also adds support for this api on Unix. --- include/uv.h | 18 ++++++++------- src/unix/process.c | 56 +++++++++++++++++++++++++--------------------- src/win/process.c | 2 +- test/test-spawn.c | 2 +- 4 files changed, 43 insertions(+), 35 deletions(-) diff --git a/include/uv.h b/include/uv.h index 9fabcd47..cda24d38 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1165,15 +1165,17 @@ UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai); /* uv_spawn() options */ typedef enum { - UV_IGNORE = 0x00, - UV_CREATE_PIPE = 0x01, - /* - * UV_READABLE_PIPE and UV_WRITABLE_PIPE flags are set from - * the child process perspective. + UV_IGNORE = 0x00, + UV_CREATE_PIPE = 0x01, + UV_INHERIT_FD = 0x02, + UV_INHERIT_STREAM = 0x04, + + /* When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE + * determine the direction of flow, from the child process' perspective. Both + * flags may be specified to create a duplex data stream. */ - UV_READABLE_PIPE = 0x02, - UV_WRITABLE_PIPE = 0x04, - UV_RAW_FD = 0x08 + UV_READABLE_PIPE = 0x10, + UV_WRITABLE_PIPE = 0x20, } uv_stdio_flags; typedef struct uv_stdio_container_s { diff --git a/src/unix/process.c b/src/unix/process.c index 2d90d97d..7584d928 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -140,33 +140,39 @@ int uv__make_pipe(int fds[2], int flags) { */ 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); + int fd = -1; + switch (container->flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | + UV_INHERIT_STREAM)) { + case UV_IGNORE: + return 0; + case UV_CREATE_PIPE: + assert(container->data.stream != NULL); - if (container->data.stream->type != UV_NAMED_PIPE) { - errno = EINVAL; + if (container->data.stream->type != UV_NAMED_PIPE) { + errno = EINVAL; + return -1; + } + + return uv__make_socketpair(fds, 0); + case UV_INHERIT_FD: + case UV_INHERIT_STREAM: + if (container->flags & UV_INHERIT_FD) { + fd = container->data.fd; + } else { + fd = container->data.stream->fd; + } + + if (fd == -1) { + errno = EINVAL; + return -1; + } + + fds[writable ? 1 : 0] = fd; + + return 0; + default: + assert(0 && "Unexpected flags"); 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; } } diff --git a/src/win/process.c b/src/win/process.c index fa409e3b..efdf27a0 100644 --- a/src/win/process.c +++ b/src/win/process.c @@ -947,7 +947,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, continue; } - if (options.stdio[i].flags & UV_RAW_FD) { + if (options.stdio[i].flags & UV_INHERIT_FD) { err = duplicate_fd(loop, options.stdio[i].data.fd, &child_stdio[i]); } else if (options.stdio[i].data.stream->type == UV_NAMED_PIPE) { pipe = (uv_pipe_t*)options.stdio[i].data.stream; diff --git a/test/test-spawn.c b/test/test-spawn.c index 5af76406..81de381e 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -221,7 +221,7 @@ TEST_IMPL(spawn_stdout_to_file) { options.stdio = stdio; options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_RAW_FD; + options.stdio[1].flags = UV_INHERIT_FD; options.stdio[1].data.fd = file; options.stdio_count = 2;