win: unregister process handle on error
The first thing uv_spawn() does is call uv__process_init(), which in turn calls uv__handle_init(), which, three layers deep, sneakily adds the handle to the event loop's handle queue. Remove the handle from said queue if we bail out early because of an error. I reworked uv_spawn to have a single exit and remove the twisty little maze of goto labels. There are still lots of gotos but only a single label now. Reported by @HACKE-RC.
This commit is contained in:
parent
a43e543dbf
commit
758846146e
@ -891,11 +891,15 @@ int uv_spawn(uv_loop_t* loop,
|
||||
uv_process_t* process,
|
||||
const uv_process_options_t* options) {
|
||||
int i;
|
||||
int err = 0;
|
||||
WCHAR* path = NULL, *alloc_path = NULL;
|
||||
int err;
|
||||
BOOL result;
|
||||
WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
|
||||
*env = NULL, *cwd = NULL;
|
||||
WCHAR* alloc_path = NULL;
|
||||
WCHAR* application = NULL;
|
||||
WCHAR* application_path = NULL;
|
||||
WCHAR* arguments = NULL;
|
||||
WCHAR* cwd = NULL;
|
||||
WCHAR* env = NULL;
|
||||
WCHAR* path;
|
||||
STARTUPINFOW startup;
|
||||
PROCESS_INFORMATION info;
|
||||
DWORD process_flags, cwd_len;
|
||||
@ -906,12 +910,13 @@ int uv_spawn(uv_loop_t* loop,
|
||||
child_stdio_buffer = NULL;
|
||||
|
||||
if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
|
||||
return UV_ENOTSUP;
|
||||
err = UV_ENOTSUP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (options->file == NULL ||
|
||||
options->args == NULL) {
|
||||
return UV_EINVAL;
|
||||
if (options->file == NULL || options->args == NULL) {
|
||||
err = UV_EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
assert(options->file != NULL);
|
||||
@ -926,26 +931,26 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
err = uv__utf8_to_utf16_alloc(options->file, &application);
|
||||
if (err)
|
||||
goto done_uv;
|
||||
goto done;
|
||||
|
||||
err = make_program_args(
|
||||
options->args,
|
||||
options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
|
||||
&arguments);
|
||||
if (err)
|
||||
goto done_uv;
|
||||
goto done;
|
||||
|
||||
if (options->env) {
|
||||
err = make_program_env(options->env, &env);
|
||||
if (err)
|
||||
goto done_uv;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (options->cwd) {
|
||||
/* Explicit cwd */
|
||||
err = uv__utf8_to_utf16_alloc(options->cwd, &cwd);
|
||||
if (err)
|
||||
goto done_uv;
|
||||
goto done;
|
||||
|
||||
cwd_len = wcslen(cwd);
|
||||
} else {
|
||||
@ -954,19 +959,19 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
cwd_len = GetCurrentDirectoryW(0, NULL);
|
||||
if (!cwd_len) {
|
||||
err = GetLastError();
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR));
|
||||
if (cwd == NULL) {
|
||||
err = ERROR_OUTOFMEMORY;
|
||||
err = UV_ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = GetCurrentDirectoryW(cwd_len, cwd);
|
||||
if (r == 0 || r >= cwd_len) {
|
||||
err = GetLastError();
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -975,7 +980,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
if (cwd_len >= MAX_PATH) {
|
||||
cwd_len = GetShortPathNameW(cwd, cwd, cwd_len);
|
||||
if (cwd_len == 0) {
|
||||
err = GetLastError();
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -989,22 +994,24 @@ int uv_spawn(uv_loop_t* loop,
|
||||
if (path_len != 0) {
|
||||
alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
|
||||
if (alloc_path == NULL) {
|
||||
err = ERROR_OUTOFMEMORY;
|
||||
err = UV_ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
path = alloc_path;
|
||||
|
||||
r = GetEnvironmentVariableW(L"PATH", path, path_len);
|
||||
if (r == 0 || r >= path_len) {
|
||||
err = GetLastError();
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = uv__stdio_create(loop, options, &child_stdio_buffer);
|
||||
if (err)
|
||||
if (err) {
|
||||
err = uv_translate_sys_error(err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
application_path = search_path(application,
|
||||
cwd,
|
||||
@ -1012,7 +1019,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
options->flags);
|
||||
if (application_path == NULL) {
|
||||
/* Not found. */
|
||||
err = ERROR_FILE_NOT_FOUND;
|
||||
err = UV_ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -1075,7 +1082,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
&startup,
|
||||
&info)) {
|
||||
/* CreateProcessW failed. */
|
||||
err = GetLastError();
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -1103,7 +1110,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
if (process_flags & CREATE_SUSPENDED) {
|
||||
if (ResumeThread(info.hThread) == ((DWORD)-1)) {
|
||||
err = GetLastError();
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
TerminateProcess(info.hProcess, 1);
|
||||
goto done;
|
||||
}
|
||||
@ -1140,20 +1147,16 @@ int uv_spawn(uv_loop_t* loop,
|
||||
/* Make the handle active. It will remain active until the exit callback is
|
||||
* made or the handle is closed, whichever happens first. */
|
||||
uv__handle_start(process);
|
||||
|
||||
goto done_uv;
|
||||
err = 0;
|
||||
|
||||
/* Cleanup, whether we succeeded or failed. */
|
||||
done:
|
||||
err = uv_translate_sys_error(err);
|
||||
|
||||
done_uv:
|
||||
done:
|
||||
uv__free(alloc_path);
|
||||
uv__free(application);
|
||||
uv__free(application_path);
|
||||
uv__free(arguments);
|
||||
uv__free(cwd);
|
||||
uv__free(env);
|
||||
uv__free(alloc_path);
|
||||
|
||||
if (child_stdio_buffer != NULL) {
|
||||
/* Clean up child stdio handles. */
|
||||
@ -1161,6 +1164,10 @@ int uv_spawn(uv_loop_t* loop,
|
||||
child_stdio_buffer = NULL;
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
uv__queue_remove(&process->handle_queue);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user