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;
|
uv_loop_t* loop = handle->loop;
|
||||||
|
|
||||||
assert(handle->flags & UV_CLOSING);
|
assert(handle->flags & UV_CLOSING);
|
||||||
assert(!(handle->flags & UV_CLOSED));
|
|
||||||
handle->flags |= UV_CLOSED;
|
handle->flags |= UV_CLOSED;
|
||||||
|
|
||||||
switch (handle->type) {
|
switch (handle->type) {
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <fcntl.h> /* O_CLOEXEC, O_NONBLOCK */
|
#include <fcntl.h> /* O_CLOEXEC, O_NONBLOCK */
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -37,6 +38,11 @@
|
|||||||
extern char **environ;
|
extern char **environ;
|
||||||
#endif
|
#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) {
|
static void uv__chld(EV_P_ ev_child* watcher, int revents) {
|
||||||
int status = watcher->rstatus;
|
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);
|
return uv__make_pipe(fds, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _detach_cb() {
|
||||||
|
/* TODO: Does something need to happen here? */
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef SPAWN_WAIT_EXEC
|
#ifndef SPAWN_WAIT_EXEC
|
||||||
# define SPAWN_WAIT_EXEC 1
|
# define SPAWN_WAIT_EXEC 1
|
||||||
@ -175,26 +184,44 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
|||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int flags;
|
int flags;
|
||||||
|
int *pid_map;
|
||||||
|
|
||||||
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
|
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
|
||||||
loop->counters.process_init++;
|
loop->counters.process_init++;
|
||||||
|
|
||||||
process->exit_cb = options.exit_cb;
|
process->exit_cb = options.exit_cb;
|
||||||
|
|
||||||
if (options.stdin_stream &&
|
if (options.detached) {
|
||||||
uv__process_init_pipe(options.stdin_stream, stdin_pipe, 0)) {
|
pid_map = mmap(0, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||||
goto error;
|
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.stderr_stream &&
|
||||||
|
uv__process_init_pipe(options.stderr_stream, stderr_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This pipe is used by the parent to wait until
|
/* This pipe is used by the parent to wait until
|
||||||
* the child has called `execve()`. We need this
|
* 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);
|
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)) {
|
if (options.cwd && chdir(options.cwd)) {
|
||||||
perror("chdir()");
|
perror("chdir()");
|
||||||
_exit(127);
|
_exit(127);
|
||||||
@ -293,7 +335,14 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
|||||||
uv__close(signal_pipe[0]);
|
uv__close(signal_pipe[0]);
|
||||||
#endif
|
#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_init(&process->child_watcher, uv__chld, pid, 0);
|
||||||
ev_child_start(process->loop->ev, &process->child_watcher);
|
ev_child_start(process->loop->ev, &process->child_watcher);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user