unix: Implement options.detached for uv_spawn() for unix.
This commit is contained in:
parent
b3e0ad4db8
commit
149d32cb96
@ -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) {
|
||||
|
||||
@ -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>
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -175,12 +184,28 @@ 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.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;
|
||||
@ -195,6 +220,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
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
|
||||
@ -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);
|
||||
@ -293,7 +335,14 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
uv__close(signal_pipe[0]);
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user