diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -15,18 +15,11 @@ #if SANITIZER_POSIX -#include "sanitizer_common.h" -#include "sanitizer_flags.h" -#include "sanitizer_platform_limits_netbsd.h" -#include "sanitizer_platform_limits_posix.h" -#include "sanitizer_platform_limits_solaris.h" -#include "sanitizer_posix.h" -#include "sanitizer_procmaps.h" - #include #include #include #include +#include #include #include #include @@ -36,6 +29,14 @@ #include #include +#include "sanitizer_common.h" +#include "sanitizer_flags.h" +#include "sanitizer_platform_limits_netbsd.h" +#include "sanitizer_platform_limits_posix.h" +#include "sanitizer_platform_limits_solaris.h" +#include "sanitizer_posix.h" +#include "sanitizer_procmaps.h" + #if SANITIZER_FREEBSD // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before // that, it was never implemented. So just define it to zero. @@ -421,6 +422,82 @@ } #endif // !SANITIZER_GO +// Android < P (r28) does not have posix_spawn +#if !SANITIZER_ANDROID || __ANDROID_API__ >= 28 +pid_t StartSubprocess(const char *program, const char *const argv[], + const char *const envp[], fd_t stdin_fd, fd_t stdout_fd, + fd_t stderr_fd) { + auto file_closer = at_scope_exit([&] { + if (stdin_fd != kInvalidFd) { + internal_close(stdin_fd); + } + if (stdout_fd != kInvalidFd) { + internal_close(stdout_fd); + } + if (stderr_fd != kInvalidFd) { + internal_close(stderr_fd); + } + }); + + int rc; + posix_spawn_file_actions_t file_actions; + if (0 != (rc = posix_spawn_file_actions_init(&file_actions))) { + Report("WARNING: posix_spawn_file_actions_init failed (rc %d)\n", rc); + return -1; + } + + auto file_actions_destroyer = + at_scope_exit([&] { posix_spawn_file_actions_destroy(&file_actions); }); + + if (stdin_fd != kInvalidFd) { + rc = + posix_spawn_file_actions_adddup2(&file_actions, stdin_fd, STDIN_FILENO); + if (rc != 0) { + Report("WARNING: posix_spawn_file_actions_adddup2 failed (rc %d)\n", rc); + return -1; + } + } + if (stdout_fd != kInvalidFd) { + rc = posix_spawn_file_actions_adddup2(&file_actions, stdout_fd, + STDOUT_FILENO); + if (rc != 0) { + Report("WARNING: posix_spawn_file_actions_adddup2 failed (rc %d)\n", rc); + return -1; + } + } + if (stderr_fd != kInvalidFd) { + rc = posix_spawn_file_actions_adddup2(&file_actions, stderr_fd, + STDERR_FILENO); + if (rc != 0) { + Report("WARNING: posix_spawn_file_actions_adddup2 failed (rc %d)\n", rc); + return -1; + } + } + + for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--) { + errno = 0; + if ((fcntl(fd, F_GETFL) != -1) || (errno != EBADF)) { + rc = posix_spawn_file_actions_addclose(&file_actions, fd); + if (rc != 0) { + Report("WARNING: posix_spawn_file_actions_addclose failed (rc %d)\n", + rc); + return -1; + } + } + } + + int pid = -1; + rc = posix_spawn(&pid, program, &file_actions, nullptr, + const_cast(argv), + const_cast(envp)); + if (rc != 0) { + Report("WARNING: posix_spawn failed (rc %d)\n", rc); + return -1; + } + + return pid; +} +#else pid_t StartSubprocess(const char *program, const char *const argv[], const char *const envp[], fd_t stdin_fd, fd_t stdout_fd, fd_t stderr_fd) { @@ -473,6 +550,7 @@ return pid; } +#endif bool IsProcessRunning(pid_t pid) { int process_status;