|
@@ -0,0 +1,111 @@
|
|
|
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
+From: Jameson Nash <[email protected]>
|
|
|
+Date: Fri, 15 Apr 2022 14:10:27 -0400
|
|
|
+Subject: macos: avoid posix_spawnp() cwd bug (#3597)
|
|
|
+
|
|
|
+macOS 10.15 has a bug where configuring the working directory with
|
|
|
+posix_spawn_file_actions_addchdir_np() makes posix_spawnp() fail with
|
|
|
+ENOENT even though the executable is spawned successfully.
|
|
|
+
|
|
|
+diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
|
|
+index c8816b85b7e531648064e739fb89257565ad64bb..de51bac3d0e8daf519d35c6a3994f1479590607a 100644
|
|
|
+--- a/deps/uv/src/unix/process.c
|
|
|
++++ b/deps/uv/src/unix/process.c
|
|
|
+@@ -671,27 +671,25 @@ static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options,
|
|
|
+ if (options->env != NULL)
|
|
|
+ env = options->env;
|
|
|
+
|
|
|
+- /* If options->file contains a slash, posix_spawn/posix_spawnp behave
|
|
|
+- * the same, and don't involve PATH resolution at all. Otherwise, if
|
|
|
+- * options->file does not include a slash, but no custom environment is
|
|
|
+- * to be used, the environment used for path resolution as well for the
|
|
|
+- * child process is that of the parent process, so posix_spawnp is the
|
|
|
+- * way to go. */
|
|
|
+- if (strchr(options->file, '/') != NULL || options->env == NULL) {
|
|
|
++ /* If options->file contains a slash, posix_spawn/posix_spawnp should behave
|
|
|
++ * the same, and do not involve PATH resolution at all. The libc
|
|
|
++ * `posix_spawnp` provided by Apple is buggy (since 10.15), so we now emulate it
|
|
|
++ * here, per https://github.com/libuv/libuv/pull/3583. */
|
|
|
++ if (strchr(options->file, '/') != NULL) {
|
|
|
+ do
|
|
|
+- err = posix_spawnp(pid, options->file, actions, attrs, options->args, env);
|
|
|
++ err = posix_spawn(pid, options->file, actions, attrs, options->args, env);
|
|
|
+ while (err == EINTR);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Look for the definition of PATH in the provided env */
|
|
|
+- path = uv__spawn_find_path_in_env(options->env);
|
|
|
++ path = uv__spawn_find_path_in_env(env);
|
|
|
+
|
|
|
+ /* The following resolution logic (execvpe emulation) is copied from
|
|
|
+ * https://git.musl-libc.org/cgit/musl/tree/src/process/execvp.c
|
|
|
+ * and adapted to work for our specific usage */
|
|
|
+
|
|
|
+- /* If no path was provided in options->env, use the default value
|
|
|
++ /* If no path was provided in env, use the default value
|
|
|
+ * to look for the executable */
|
|
|
+ if (path == NULL)
|
|
|
+ path = _PATH_DEFPATH;
|
|
|
+diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
|
|
|
+index 199402e31406cf8ba360d54769461bb5285011ee..f8c08a4a7eb164ffff495c81e1f5df712084648b 100644
|
|
|
+--- a/deps/uv/test/test-list.h
|
|
|
++++ b/deps/uv/test/test-list.h
|
|
|
+@@ -322,6 +322,7 @@ TEST_DECLARE (spawn_inherit_streams)
|
|
|
+ TEST_DECLARE (spawn_quoted_path)
|
|
|
+ TEST_DECLARE (spawn_tcp_server)
|
|
|
+ TEST_DECLARE (spawn_exercise_sigchld_issue)
|
|
|
++TEST_DECLARE (spawn_relative_path)
|
|
|
+ TEST_DECLARE (fs_poll)
|
|
|
+ TEST_DECLARE (fs_poll_getpath)
|
|
|
+ TEST_DECLARE (fs_poll_close_request)
|
|
|
+@@ -954,6 +955,7 @@ TASK_LIST_START
|
|
|
+ TEST_ENTRY (spawn_quoted_path)
|
|
|
+ TEST_ENTRY (spawn_tcp_server)
|
|
|
+ TEST_ENTRY (spawn_exercise_sigchld_issue)
|
|
|
++ TEST_ENTRY (spawn_relative_path)
|
|
|
+ TEST_ENTRY (fs_poll)
|
|
|
+ TEST_ENTRY (fs_poll_getpath)
|
|
|
+ TEST_ENTRY (fs_poll_close_request)
|
|
|
+diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
|
|
|
+index dfd5458ef37c664af9a55a8383bdb3121885db3b..de9c710020ef7da66e45f5617a8a697e698fa202 100644
|
|
|
+--- a/deps/uv/test/test-spawn.c
|
|
|
++++ b/deps/uv/test/test-spawn.c
|
|
|
+@@ -1981,3 +1981,37 @@ void spawn_stdin_stdout(void) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endif /* !_WIN32 */
|
|
|
++
|
|
|
++TEST_IMPL(spawn_relative_path) {
|
|
|
++ char* sep;
|
|
|
++
|
|
|
++ init_process_options("spawn_helper1", exit_cb);
|
|
|
++
|
|
|
++ exepath_size = sizeof(exepath) - 2;
|
|
|
++ ASSERT_EQ(0, uv_exepath(exepath, &exepath_size));
|
|
|
++ exepath[exepath_size] = '\0';
|
|
|
++
|
|
|
++ /* Poor man's basename(3). */
|
|
|
++ sep = strrchr(exepath, '/');
|
|
|
++ if (sep == NULL)
|
|
|
++ sep = strrchr(exepath, '\\');
|
|
|
++ ASSERT_NOT_NULL(sep);
|
|
|
++
|
|
|
++ /* Split into dirname and basename and make basename relative. */
|
|
|
++ memmove(sep + 2, sep, 1 + strlen(sep));
|
|
|
++ sep[0] = '\0';
|
|
|
++ sep[1] = '.';
|
|
|
++ sep[2] = '/';
|
|
|
++
|
|
|
++ options.cwd = exepath;
|
|
|
++ options.file = options.args[0] = sep + 1;
|
|
|
++
|
|
|
++ ASSERT_EQ(0, uv_spawn(uv_default_loop(), &process, &options));
|
|
|
++ ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
|
|
++
|
|
|
++ ASSERT_EQ(1, exit_cb_called);
|
|
|
++ ASSERT_EQ(1, close_cb_called);
|
|
|
++
|
|
|
++ MAKE_VALGRIND_HAPPY();
|
|
|
++ return 0;
|
|
|
++}
|