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
process: implement UV_PROCESS_DETACHED flag for uv_spawn
  • Loading branch information
AvianFlu authored and piscisaureus committed Jun 1, 2012
1 parent aecddfe commit 69a923b
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 3 deletions.
10 changes: 9 additions & 1 deletion include/uv.h
Expand Up @@ -1246,7 +1246,15 @@ enum uv_process_flags {
* converting the argument list into a command line string. This option is
* only meaningful on Windows systems. On unix it is silently ignored.
*/
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2)
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
/*
* Spawn the child process in a detached state - this will make it a process
* group leader, and will effectively enable the child to keep running after
* the parent exits. Note that the child process will still keep the
* parent's event loop alive unless the parent process calls uv_unref() on
* the child's process handle.
*/
UV_PROCESS_DETACHED = (1 << 3)
};

/*
Expand Down
4 changes: 4 additions & 0 deletions src/unix/process.c
Expand Up @@ -240,6 +240,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,

assert(options.file != NULL);
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID)));

Expand Down Expand Up @@ -301,6 +302,9 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,

if (pid == 0) {
/* Child */
if (options.flags & UV_PROCESS_DETACHED) {
setsid();
}

/* Dup fds */
for (i = 0; i < options.stdio_count; i++) {
Expand Down
10 changes: 8 additions & 2 deletions src/win/process.c
Expand Up @@ -869,7 +869,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
int err = 0, keep_child_stdio_open = 0;
wchar_t* path = NULL;
int size, i, overlapped;
DWORD server_access, child_access;
DWORD server_access, child_access,
process_flags = CREATE_UNICODE_ENVIRONMENT;
BOOL result;
wchar_t* application_path = NULL, *application = NULL, *arguments = NULL,
*env = NULL, *cwd = NULL;
Expand All @@ -891,6 +892,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,

assert(options.file != NULL);
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
UV_PROCESS_SETUID)));

Expand Down Expand Up @@ -1005,12 +1007,16 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
startup.hStdOutput = child_stdio[1];
startup.hStdError = child_stdio[2];

if (options.flags & UV_PROCESS_DETACHED) {
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
}

if (CreateProcessW(application_path,
arguments,
NULL,
NULL,
1,
CREATE_UNICODE_ENVIRONMENT,
process_flags,
env,
cwd,
&startup,
Expand Down
2 changes: 2 additions & 0 deletions test/test-list.h
Expand Up @@ -120,6 +120,7 @@ TEST_DECLARE (spawn_exit_code)
TEST_DECLARE (spawn_stdout)
TEST_DECLARE (spawn_stdin)
TEST_DECLARE (spawn_and_kill)
TEST_DECLARE (spawn_detached)
TEST_DECLARE (spawn_and_kill_with_std)
TEST_DECLARE (spawn_and_ping)
TEST_DECLARE (spawn_setuid_fails)
Expand Down Expand Up @@ -333,6 +334,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_stdout)
TEST_ENTRY (spawn_stdin)
TEST_ENTRY (spawn_and_kill)
TEST_ENTRY (spawn_detached)
TEST_ENTRY (spawn_and_kill_with_std)
TEST_ENTRY (spawn_and_ping)
TEST_ENTRY (spawn_setuid_fails)
Expand Down
31 changes: 31 additions & 0 deletions test/test-spawn.c
Expand Up @@ -99,6 +99,11 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
ASSERT(err.code == UV_ESRCH);
}

static void detach_failure_cb(uv_process_t* process, int exit_status, int term_signal) {
uv_err_t err;
printf("detach_cb\n");
exit_cb_called++;
}

static uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) {
uv_buf_t buf;
Expand Down Expand Up @@ -314,6 +319,32 @@ TEST_IMPL(spawn_and_kill) {
return 0;
}

TEST_IMPL(spawn_detached) {
int r;
uv_err_t err;

init_process_options("spawn_helper4", detach_failure_cb);

options.flags |= UV_PROCESS_DETACHED;

r = uv_spawn(uv_default_loop(), &process, options);
ASSERT(r == 0);

uv_unref((uv_handle_t*)&process);

r = uv_run(uv_default_loop());
ASSERT(r == 0);

ASSERT(exit_cb_called == 0);

err = uv_kill(process.pid, 0);
ASSERT(err.code == 0);

err = uv_kill(process.pid, 15);
ASSERT(err.code == 0);

return 0;
}

TEST_IMPL(spawn_and_kill_with_std) {
int r;
Expand Down

0 comments on commit 69a923b

Please sign in to comment.