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

Commit

Permalink
Browse files Browse the repository at this point in the history
unix: Implement options.detached for uv_spawn() for unix.
  • Loading branch information
AvianFlu authored and bnoordhuis committed Feb 24, 2012
1 parent b3e0ad4 commit 149d32c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
1 change: 0 additions & 1 deletion src/unix/core.c
Expand Up @@ -239,7 +239,6 @@ void uv__finish_close(uv_handle_t* handle) {
uv_loop_t* loop = handle->loop;

assert(handle->flags & UV_CLOSING);
assert(!(handle->flags & UV_CLOSED));
handle->flags |= UV_CLOSED;

switch (handle->type) {
Expand Down
73 changes: 61 additions & 12 deletions src/unix/process.c
Expand Up @@ -25,6 +25,7 @@
#include <assert.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h> /* O_CLOEXEC, O_NONBLOCK */
#include <poll.h>
#include <unistd.h>
Expand All @@ -37,6 +38,11 @@
extern char **environ;
#endif

#ifndef MAP_ANONYMOUS
#ifdef MAP_ANON
#define MAP_ANONYMOUS MAP_ANON
#endif
#endif

static void uv__chld(EV_P_ ev_child* watcher, int revents) {
int status = watcher->rstatus;
Expand Down Expand Up @@ -153,6 +159,9 @@ static int uv__process_init_pipe(uv_pipe_t* handle, int fds[2], int flags) {
return uv__make_pipe(fds, flags);
}

void _detach_cb() {
/* TODO: Does something need to happen here? */
}

#ifndef SPAWN_WAIT_EXEC
# define SPAWN_WAIT_EXEC 1
Expand All @@ -175,27 +184,45 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
int status;
pid_t pid;
int flags;
int *pid_map;

uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
loop->counters.process_init++;

process->exit_cb = options.exit_cb;

if (options.stdin_stream &&
uv__process_init_pipe(options.stdin_stream, stdin_pipe, 0)) {
goto error;
}
if (options.detached) {
pid_map = mmap(0, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (pid_map == MAP_FAILED) {
goto error;
}
if (options.stdin_stream) {
uv_close((uv_handle_t*)options.stdin_stream, _detach_cb);
}
if (options.stdout_stream) {
uv_close((uv_handle_t*)options.stdout_stream, _detach_cb);
}
if (options.stderr_stream) {
uv_close((uv_handle_t*)options.stderr_stream, _detach_cb);
}
} else {
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;
}
if (options.stdout_stream &&
uv__process_init_pipe(options.stdout_stream, stdout_pipe, 0)) {
goto error;
}

if (options.stderr_stream &&
uv__process_init_pipe(options.stderr_stream, stderr_pipe, 0)) {
goto error;
if (options.stderr_stream &&
uv__process_init_pipe(options.stderr_stream, stderr_pipe, 0)) {
goto error;
}
}


/* This pipe is used by the parent to wait until
* the child has called `execve()`. We need this
* to avoid the following race condition:
Expand Down Expand Up @@ -260,6 +287,21 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
uv__nonblock(STDERR_FILENO, 0);
}

if (options.detached) {
setsid();
umask(027);
pid = fork();
if (pid < 0) {
perror("Second fork()");
_exit(errno);
} else if (pid > 0) {
/* First child saves the pid of the second child and exits. */
pid_map[0] = pid;
exit(0);
}
/* Second child continues below */
}

if (options.cwd && chdir(options.cwd)) {
perror("chdir()");
_exit(127);
Expand Down Expand Up @@ -293,7 +335,14 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
uv__close(signal_pipe[0]);
#endif

process->pid = pid;
if (options.detached) {
process->pid = pid_map[0];
if (munmap(pid_map, sizeof(pid_t)) != 0) {
goto error;
}
} else {
process->pid = pid;
}

ev_child_init(&process->child_watcher, uv__chld, pid, 0);
ev_child_start(process->loop->ev, &process->child_watcher);
Expand Down

0 comments on commit 149d32c

Please sign in to comment.