Created
May 13, 2020 23:28
-
-
Save fredemmott/984c00d869740b5de00294b80b7e0a89 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/hphp/hack/hhi/hsl/ext_hsl_os_subprocesses.hhi b/hphp/hack/hhi/hsl/ext_hsl_os_subprocesses.hhi | |
index 59f4eb477b..9a0d09b546 100644 | |
--- a/hphp/hack/hhi/hsl/ext_hsl_os_subprocesses.hhi | |
+++ b/hphp/hack/hhi/hsl/ext_hsl_os_subprocesses.hhi | |
@@ -15,6 +15,7 @@ use type HH\Lib\OS\FileDescriptor; | |
type ForkAndExecveOptions = shape( | |
?'cwd' => string, | |
?'setsid' => bool, | |
+ ?'execvpe' => bool, | |
?'setpgid' => int, | |
); | |
diff --git a/hphp/runtime/ext/hsl/ext_hsl_os.cpp b/hphp/runtime/ext/hsl/ext_hsl_os.cpp | |
index 4de7bb8245..0b255004d8 100644 | |
--- a/hphp/runtime/ext/hsl/ext_hsl_os.cpp | |
+++ b/hphp/runtime/ext/hsl/ext_hsl_os.cpp | |
@@ -910,7 +910,8 @@ Object HHVM_FUNCTION(HSL_os_poll_async, | |
const StaticString | |
s_cwd("cwd"), | |
s_setsid("setsid"), | |
- s_setpgid("setpgid"); | |
+ s_setpgid("setpgid"), | |
+ s_execvpe("execvpe"); | |
int64_t HHVM_FUNCTION(HSL_os_fork_and_execve, | |
const String& path, | |
@@ -955,6 +956,16 @@ int64_t HHVM_FUNCTION(HSL_os_fork_and_execve, | |
flags |= Process::FORK_AND_EXECVE_FLAG_SETPGID; | |
} | |
+ if (options.exists(s_execvpe)) { | |
+ const auto& val = options[s_execvpe]; | |
+ if (!val.isBoolean()) { | |
+ throw_errno_exception(EINVAL, "'execvpe' option must be a bool"); | |
+ } | |
+ if (val.asBooleanVal()) { | |
+ flags |= Process::FORK_AND_EXECVE_FLAG_EXECVPE; | |
+ } | |
+ } | |
+ | |
auto vec_str_to_cpp_arr = ([] (const Array& vec) { | |
std::vector<std::string> arr; | |
for (ArrayIter iter(vec); iter; ++iter) { | |
diff --git a/hphp/util/process.cpp b/hphp/util/process.cpp | |
index 5300b3e519..22d98dbee5 100644 | |
--- a/hphp/util/process.cpp | |
+++ b/hphp/util/process.cpp | |
@@ -32,6 +32,10 @@ | |
#include <folly/portability/Unistd.h> | |
#endif | |
+#ifdef __APPLE__ | |
+#include <crt_externs.h> | |
+#endif | |
+ | |
#include <folly/Conv.h> | |
#include <folly/Format.h> | |
#include <folly/ScopeGuard.h> | |
@@ -571,10 +575,43 @@ pid_t Process::ForkAndExecve( | |
} | |
char** argv_arr = build_cstrarr(argv); | |
- char** envp_arr = build_cstrarr(envp); | |
+ char** envp_arr = nullptr; | |
SCOPE_EXIT { free(argv_arr); free(envp_arr); }; | |
- execve(path.c_str(), argv_arr, envp_arr); | |
+ if (flags & Process::FORK_AND_EXECVE_FLAG_EXECVPE) { | |
+ // we could use real `execvpe` on linux, but let's just use the emulation | |
+ // everywhere so we have reliable cross-platform behavior and testability | |
+ | |
+ // We could either: | |
+ // - use `execve()` and implement our own $PATH behavior | |
+ // - use `execvp()` and implement our own envp behavior | |
+ // The latter seems less likely to lead to accidental problems, so let's | |
+ // do that. | |
+ | |
+#if defined(__linux__) | |
+ clearenv(); | |
+#elif defined(__APPLE__) | |
+ // `environ` in MacOS-speak | |
+ *(_NSGetEnviron()) = nullptr; | |
+#else | |
+ static_assert(false, "Unsupported platform"); | |
+#endif | |
+ for (const auto& var : envp) { | |
+ // Need a null-terminated, mutable char* | |
+ char* buf = (char*) malloc(var.length() + 1); | |
+ buf[var.length()] = 0; | |
+ memcpy(buf, var.c_str(), var.length()); | |
+ | |
+ if (putenv(buf) != 0) { | |
+ dprintf(fork_w, "%s %d", "putenv", errno); | |
+ _Exit(1); | |
+ } | |
+ } | |
+ execvp(path.c_str(), argv_arr); | |
+ } else { | |
+ envp_arr = build_cstrarr(envp); | |
+ execve(path.c_str(), argv_arr, envp_arr); | |
+ } | |
dprintf(fork_w, "%s %d", "execve", errno); | |
_Exit(1); | |
} | |
@@ -621,6 +658,9 @@ pid_t Process::ForkAndExecve( | |
if (failed_call == "execve") { | |
return -5; | |
} | |
+ if (failed_call == "putenv") { | |
+ return -6; | |
+ } | |
return -9999; | |
} | |
diff --git a/hphp/util/process.h b/hphp/util/process.h | |
index 9fd067d6d3..55c1ac0bc4 100644 | |
--- a/hphp/util/process.h | |
+++ b/hphp/util/process.h | |
@@ -258,6 +258,7 @@ struct Process { | |
static const int FORK_AND_EXECVE_FLAG_NONE = 0; | |
static const int FORK_AND_EXECVE_FLAG_SETPGID = 1 << 0; | |
static const int FORK_AND_EXECVE_FLAG_SETSID = 1 << 1; | |
+ static const int FORK_AND_EXECVE_FLAG_EXECVPE = 1 << 2; | |
/** Opens a process with the given arguments, environment, working directory, | |
* and file descriptors. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment