win: Implement options.detached for uv_spawn() for Windows.

This commit is contained in:
Charlie McConnell 2012-02-23 23:15:43 -08:00 committed by Ben Noordhuis
parent 149d32cb96
commit e99fdf0df6

View File

@ -859,6 +859,9 @@ static int duplicate_std_handle(uv_loop_t* loop, DWORD id, HANDLE* dup) {
return 0; return 0;
} }
void _detach_cb(uv_handle_t *handle) {
/* TODO: something here? */
}
int uv_spawn(uv_loop_t* loop, uv_process_t* process, int uv_spawn(uv_loop_t* loop, uv_process_t* process,
uv_process_options_t options) { uv_process_options_t options) {
@ -871,6 +874,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
HANDLE* child_stdio = process->child_stdio; HANDLE* child_stdio = process->child_stdio;
STARTUPINFOW startup; STARTUPINFOW startup;
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
DWORD process_flags;
if (!options.file) { if (!options.file) {
uv__set_artificial_error(loop, UV_EINVAL); uv__set_artificial_error(loop, UV_EINVAL);
@ -902,6 +906,25 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
} }
} }
if (options.detached) {
if (options.stdin_stream) {
uv_close((uv_handle_t*)options.stdin_stream, _detach_cb);
options.stdin_stream = NULL;
}
if (options.stdout_stream) {
uv_close((uv_handle_t*)options.stdout_stream, _detach_cb);
options.stdout_stream = NULL;
}
if (options.stderr_stream) {
uv_close((uv_handle_t*)options.stderr_stream, _detach_cb);
options.stderr_stream = NULL;
}
process_flags = CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW |
CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS;
} else {
process_flags = CREATE_UNICODE_ENVIRONMENT;
}
/* Get PATH env. variable. */ /* Get PATH env. variable. */
size = GetEnvironmentVariableW(L"PATH", NULL, 0) + 1; size = GetEnvironmentVariableW(L"PATH", NULL, 0) + 1;
path = (wchar_t*)malloc(size * sizeof(wchar_t)); path = (wchar_t*)malloc(size * sizeof(wchar_t));
@ -940,7 +963,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
GENERIC_READ | FILE_WRITE_ATTRIBUTES, GENERIC_READ | FILE_WRITE_ATTRIBUTES,
0); 0);
} }
} else { } else if (!options.detached) {
err = duplicate_std_handle(loop, STD_INPUT_HANDLE, &child_stdio[0]); err = duplicate_std_handle(loop, STD_INPUT_HANDLE, &child_stdio[0]);
} }
if (err) { if (err) {
@ -954,7 +977,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
PIPE_ACCESS_INBOUND, PIPE_ACCESS_INBOUND,
GENERIC_WRITE, GENERIC_WRITE,
0); 0);
} else { } else if (!options.detached) {
err = duplicate_std_handle(loop, STD_OUTPUT_HANDLE, &child_stdio[1]); err = duplicate_std_handle(loop, STD_OUTPUT_HANDLE, &child_stdio[1]);
} }
if (err) { if (err) {
@ -969,7 +992,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
PIPE_ACCESS_INBOUND, PIPE_ACCESS_INBOUND,
GENERIC_WRITE, GENERIC_WRITE,
0); 0);
} else { } else if (!options.detached) {
err = duplicate_std_handle(loop, STD_ERROR_HANDLE, &child_stdio[2]); err = duplicate_std_handle(loop, STD_ERROR_HANDLE, &child_stdio[2]);
} }
if (err) { if (err) {
@ -980,19 +1003,23 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
startup.lpReserved = NULL; startup.lpReserved = NULL;
startup.lpDesktop = NULL; startup.lpDesktop = NULL;
startup.lpTitle = NULL; startup.lpTitle = NULL;
startup.dwFlags = STARTF_USESTDHANDLES; if (options.detached) {
startup.dwFlags = NULL;
} else {
startup.dwFlags = STARTF_USESTDHANDLES;
}
startup.cbReserved2 = 0; startup.cbReserved2 = 0;
startup.lpReserved2 = NULL; startup.lpReserved2 = NULL;
startup.hStdInput = child_stdio[0]; startup.hStdInput = options.detached ? NULL : child_stdio[0];
startup.hStdOutput = child_stdio[1]; startup.hStdOutput = options.detached ? NULL : child_stdio[1];
startup.hStdError = child_stdio[2]; startup.hStdError = options.detached ? NULL : child_stdio[2];
if (CreateProcessW(application_path, if (CreateProcessW(application_path,
arguments, arguments,
NULL, NULL,
NULL, NULL,
1, options.detached ? 0 : 1,
CREATE_UNICODE_ENVIRONMENT, process_flags,
env, env,
cwd, cwd,
&startup, &startup,
@ -1006,15 +1033,19 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
options.stdin_stream->ipc_pid = info.dwProcessId; options.stdin_stream->ipc_pid = info.dwProcessId;
} }
/* Setup notifications for when the child process exits. */ if (!options.detached) {
result = RegisterWaitForSingleObject(&process->wait_handle, result = RegisterWaitForSingleObject(&process->wait_handle,
process->process_handle, exit_wait_callback, (void*)process, INFINITE, process->process_handle, exit_wait_callback, (void*)process, INFINITE,
WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
if (!result) { if (!result) {
uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
}
}
CloseHandle(info.hThread);
if (options.detached) {
CloseHandle(info.hProcess);
exit_wait_callback((void*)process, FALSE);
} }
CloseHandle(info.hThread);
} else { } else {
/* CreateProcessW failed, but this failure should be delivered */ /* CreateProcessW failed, but this failure should be delivered */