process: implement UV_PROCESS_DETACHED flag for uv_spawn
This commit is contained in:
parent
aecddfe530
commit
69a923bf93
10
include/uv.h
10
include/uv.h
@ -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)
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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++) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user