Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

unix: simplify stdio handling in process.c

  • Loading branch information...
commit 47f496aa65fd5e380df2f5e2d3a9c66e0b3fbb7d 1 parent 13467a4
@bnoordhuis bnoordhuis authored
Showing with 62 additions and 62 deletions.
  1. +62 −62 src/unix/process.c
View
124 src/unix/process.c
@@ -124,8 +124,7 @@ 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_stdio(uv_stdio_container_t* container, int fds[2],
- int writable) {
+static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
int fd = -1;
switch (container->flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
UV_INHERIT_STREAM)) {
@@ -153,7 +152,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2],
return -1;
}
- fds[writable ? 1 : 0] = fd;
+ fds[1] = fd;
return 0;
default:
@@ -176,16 +175,19 @@ static int uv__process_stdio_flags(uv_stdio_container_t* container,
}
-static int uv__process_open_stream(uv_stdio_container_t* container, int fds[2],
+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 child_fd;
int flags;
+ int fd;
+
+ fd = fds[0];
+ child_fd = fds[1];
/* No need to create stream */
- if (!(container->flags & UV_CREATE_PIPE) || fd < 0) {
+ if (!(container->flags & UV_CREATE_PIPE) || fd < 0)
return 0;
- }
assert(child_fd >= 0);
close(child_fd);
@@ -199,7 +201,6 @@ static int uv__process_open_stream(uv_stdio_container_t* container, int fds[2],
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);
}
@@ -233,43 +234,41 @@ static void uv__write_int(int fd, int val) {
static void uv__process_child_init(uv_process_options_t options,
int stdio_count,
- int* pipes,
+ int (*pipes)[2],
int error_fd) {
+ int close_fd;
+ int use_fd;
int i;
- if (options.flags & UV_PROCESS_DETACHED) {
+ if (options.flags & UV_PROCESS_DETACHED)
setsid();
- }
- /* Dup fds */
for (i = 0; i < 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_fd = pipes[i][0];
+ use_fd = pipes[i][1];
+
+ if (use_fd >= 0)
close(close_fd);
- } else if (i < 3) {
- /* `/dev/null` stdin, stdout, stderr even if they've flag UV_IGNORE */
+ else if (i >= 3)
+ continue;
+ else {
+ /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
+ * set
+ */
use_fd = open("/dev/null", i == 0 ? O_RDONLY : O_RDWR);
- if (use_fd < 0) {
+ if (use_fd == -1) {
uv__write_int(error_fd, errno);
perror("failed to open stdio");
_exit(127);
}
- } else {
- continue;
}
- if (i != use_fd) {
+ if (i == use_fd)
+ uv__cloexec(use_fd, 0);
+ else {
dup2(use_fd, i);
close(use_fd);
- } else {
- uv__cloexec(use_fd, 0);
}
}
@@ -300,48 +299,55 @@ static void uv__process_child_init(uv_process_options_t options,
}
-int uv_spawn(uv_loop_t* loop, 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 stdio_count = options.stdio_count < 3 ? 3 : options.stdio_count;
- int* pipes = malloc(2 * stdio_count * sizeof(int));
+int uv_spawn(uv_loop_t* loop,
+ uv_process_t* process,
+ const uv_process_options_t options) {
int signal_pipe[2] = { -1, -1 };
+ char** save_our_env;
struct pollfd pfd;
+ int (*pipes)[2];
+ int stdio_count;
pid_t pid;
int i;
int r;
- if (pipes == NULL) {
- errno = ENOMEM;
- goto error;
- }
-
assert(options.file != NULL);
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID)));
-
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
loop->counters.process_init++;
- /* Init pipe pairs */
+ /* Save environ in case it gets clobbered by the child process. */
+ save_our_env = environ;
+
+ stdio_count = options.stdio_count;
+ if (stdio_count < 3)
+ stdio_count = 3;
+
+ pipes = malloc(stdio_count * sizeof(*pipes));
+ if (pipes == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
+
for (i = 0; i < stdio_count; i++) {
- pipes[i * 2] = -1;
- pipes[i * 2 + 1] = -1;
+ pipes[i][0] = -1;
+ pipes[i][1] = -1;
}
- /* 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)) {
+ for (i = 0; i < options.stdio_count; i++)
+ if (uv__process_init_stdio(options.stdio + i, pipes[i]))
goto error;
- }
+
+ /* swap stdin file descriptors, it's the only writable stream */
+ {
+ int* p = pipes[0];
+ int t = p[0];
+ p[0] = p[1];
+ p[1] = t;
}
/* This pipe is used by the parent to wait until
@@ -411,13 +417,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
process->pid = pid;
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 (uv__process_open_stream(options.stdio + i, pipes[i], i == 0)) {
+ while (i--) uv__process_close_stream(options.stdio + i);
goto error;
}
}
@@ -431,10 +432,9 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
uv__set_sys_error(process->loop, errno);
for (i = 0; i < stdio_count; i++) {
- close(pipes[i * 2]);
- close(pipes[i * 2 + 1]);
+ close(pipes[i][0]);
+ close(pipes[i][1]);
}
-
free(pipes);
return -1;
Please sign in to comment.
Something went wrong with that request. Please try again.