Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
unix: simplify stdio handling in process.c
Browse files Browse the repository at this point in the history
  • Loading branch information
bnoordhuis committed Aug 8, 2012
1 parent 13467a4 commit 47f496a
Showing 1 changed file with 62 additions and 62 deletions.
124 changes: 62 additions & 62 deletions src/unix/process.c
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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:
Expand All @@ -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);
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
Expand Down

0 comments on commit 47f496a

Please sign in to comment.