process: implement UV_PROCESS_DETACHED flag for uv_spawn

This commit is contained in:
Charlie McConnell 2012-05-31 17:19:27 -07:00 committed by Bert Belder
parent aecddfe530
commit 69a923bf93
5 changed files with 54 additions and 3 deletions

View File

@ -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)
};
/*

View File

@ -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)));
@ -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++) {

View File

@ -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;
@ -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)));
@ -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,

View File

@ -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)
@ -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)

View File

@ -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;
@ -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;