windows: read the PATH env var of the child
The unix and windows process implementations diverge in their behavior when dealing with subprocesses that are spawned with a relative path. With unix the *child's* PATH environment variable is read, whereas with windows the *parent's* environment variable is read. This commit brings the two implementation in line with respect to their behavior of reading PATH by having both read the *child's* PATH environment variable. This involves looking into the user-provided environment on windows and extracting the PATH variable specifically so it can be inspected later on.
This commit is contained in:
parent
d802486232
commit
c7e4b31444
@ -813,6 +813,20 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to find the value of the PATH environment variable in the child's
|
||||
* preprocessed environment.
|
||||
*
|
||||
* If found, a pointer into `env` is returned. If not found, NULL is returned.
|
||||
*/
|
||||
static WCHAR* find_path(WCHAR *env) {
|
||||
for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
|
||||
if (wcsncmp(env, L"PATH=", 5) == 0)
|
||||
return &env[5];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called on Windows thread-pool thread to indicate that
|
||||
@ -910,7 +924,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
const uv_process_options_t* options) {
|
||||
int i;
|
||||
int err = 0;
|
||||
WCHAR* path = NULL;
|
||||
WCHAR* path = NULL, *alloc_path = NULL;
|
||||
BOOL result;
|
||||
WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
|
||||
*env = NULL, *cwd = NULL;
|
||||
@ -984,7 +998,8 @@ int uv_spawn(uv_loop_t* loop,
|
||||
}
|
||||
|
||||
/* Get PATH environment variable. */
|
||||
{
|
||||
path = find_path(env);
|
||||
if (path == NULL) {
|
||||
DWORD path_len, r;
|
||||
|
||||
path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
|
||||
@ -993,11 +1008,12 @@ int uv_spawn(uv_loop_t* loop,
|
||||
goto done;
|
||||
}
|
||||
|
||||
path = (WCHAR*) malloc(path_len * sizeof(WCHAR));
|
||||
if (path == NULL) {
|
||||
alloc_path = (WCHAR*) malloc(path_len * sizeof(WCHAR));
|
||||
if (alloc_path == NULL) {
|
||||
err = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
path = alloc_path;
|
||||
|
||||
r = GetEnvironmentVariableW(L"PATH", path, path_len);
|
||||
if (r == 0 || r >= path_len) {
|
||||
@ -1131,7 +1147,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
free(arguments);
|
||||
free(cwd);
|
||||
free(env);
|
||||
free(path);
|
||||
free(alloc_path);
|
||||
|
||||
if (process->child_stdio_buffer != NULL) {
|
||||
/* Clean up child stdio handles. */
|
||||
|
||||
@ -192,6 +192,7 @@ TEST_DECLARE (spawn_stdout_to_file)
|
||||
TEST_DECLARE (spawn_stdout_and_stderr_to_file)
|
||||
TEST_DECLARE (spawn_auto_unref)
|
||||
TEST_DECLARE (spawn_closed_process_io)
|
||||
TEST_DECLARE (spawn_reads_child_path)
|
||||
TEST_DECLARE (fs_poll)
|
||||
TEST_DECLARE (fs_poll_getpath)
|
||||
TEST_DECLARE (kill)
|
||||
@ -520,6 +521,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (spawn_stdout_and_stderr_to_file)
|
||||
TEST_ENTRY (spawn_auto_unref)
|
||||
TEST_ENTRY (spawn_closed_process_io)
|
||||
TEST_ENTRY (spawn_reads_child_path)
|
||||
TEST_ENTRY (fs_poll)
|
||||
TEST_ENTRY (fs_poll_getpath)
|
||||
TEST_ENTRY (kill)
|
||||
|
||||
@ -1291,3 +1291,38 @@ TEST_IMPL(closed_fd_events) {
|
||||
return 0;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
TEST_IMPL(spawn_reads_child_path) {
|
||||
int r;
|
||||
int len;
|
||||
char path[1024];
|
||||
char *env[2] = {path, NULL};
|
||||
|
||||
/* Set up the process, but make sure that the file to run is relative and */
|
||||
/* requires a lookup into PATH */
|
||||
init_process_options("spawn_helper1", exit_cb);
|
||||
options.file = "run-tests";
|
||||
args[0] = "run-tests";
|
||||
|
||||
/* Set up the PATH env variable */
|
||||
for (len = strlen(exepath);
|
||||
exepath[len - 1] != '/' && exepath[len - 1] != '\\';
|
||||
len--);
|
||||
exepath[len] = 0;
|
||||
strcpy(path, "PATH=");
|
||||
strcpy(path + 5, exepath);
|
||||
|
||||
options.env = env;
|
||||
|
||||
r = uv_spawn(uv_default_loop(), &process, &options);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(exit_cb_called == 1);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user