Index: lib/sanitizer_common/sanitizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,8 @@ #define MAP_NORESERVE 0 #endif +extern char **environ; + typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); namespace __sanitizer { @@ -434,6 +437,65 @@ } #endif // !SANITIZER_GO +// Android < P (r28) does not have posix_spawn, so for now we use the old fork- +// based implementation there. Hopefully some day we'll only care about recent +// Android and we can drop that. +#if !SANITIZER_ANDROID || __ANDROID_API__ >= 28 +pid_t StartSubprocess(const char *program, const char *const argv[], + 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); + } + }); + + posix_spawn_file_actions_t fa; + int result = posix_spawn_file_actions_init(&fa); + if (result != 0) { + Report("WARNING: posix_spawn_file_actions_init failed (result %d)\n", result); + return -1; + } + auto file_actions_destroyer = at_scope_exit([&] { + posix_spawn_file_actions_destroy(&fa); + }); + + if (stdin_fd != kInvalidFd) { + result = posix_spawn_file_actions_adddup2(&fa, stdin_fd, STDIN_FILENO); + if (result != 0) { + Report("WARNING: posix_spawn_file_actions_adddup2 failed (result %d)\n", result); + return -1; + } + } + if (stdout_fd != kInvalidFd) { + result = posix_spawn_file_actions_adddup2(&fa, stdout_fd, STDOUT_FILENO); + if (result != 0) { + Report("WARNING: posix_spawn_file_actions_adddup2 failed (result %d)\n", result); + return -1; + } + } + if (stderr_fd != kInvalidFd) { + result = posix_spawn_file_actions_adddup2(&fa, stderr_fd, STDERR_FILENO); + if (result != 0) { + Report("WARNING: posix_spawn_file_actions_adddup2 failed (result %d)\n", result); + return -1; + } + } + + pid_t pid; + result = posix_spawn(&pid, program, &fa, nullptr, const_cast(argv), environ); + if (result != 0) { + Report("WARNING: failed to spawn process (result %d)\n", result); + return -1; + } + return pid; +} +#else pid_t StartSubprocess(const char *program, const char *const argv[], fd_t stdin_fd, fd_t stdout_fd, fd_t stderr_fd) { auto file_closer = at_scope_exit([&] { @@ -484,6 +546,7 @@ return pid; } +#endif bool IsProcessRunning(pid_t pid) { int process_status;