diff options
author | Mike Aizatsky <aizatsky@chromium.org> | 2016-01-25 19:43:52 +0000 |
---|---|---|
committer | Mike Aizatsky <aizatsky@chromium.org> | 2016-01-25 19:43:52 +0000 |
commit | e5b34d5a2bf4c882bc647dd26a8cea2adc76f63c (patch) | |
tree | e639ca0a5205bb8c229aeb5489e05fae12ba330f /lib/sanitizer_common/sanitizer_linux_libcdep.cc | |
parent | aa7bb0678b43fddff39583510a9a665c447d0b47 (diff) |
[sanitizers] extracted process management functions
Differential Revision: http://reviews.llvm.org/D16542
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@258710 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_linux_libcdep.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux_libcdep.cc | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 8cf2c73b1..7a4592e6b 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -34,6 +34,7 @@ #include <pthread.h> #include <signal.h> #include <sys/resource.h> +#include <sys/wait.h> #if SANITIZER_FREEBSD #include <pthread_np.h> @@ -546,6 +547,73 @@ void LogMessageOnPrintf(const char *str) { WriteToSyslog(str); } +int StartSubprocess(const char *program, char *const argv[], fd_t std_in_fd, + fd_t std_out_fd, fd_t std_err_fd) { + auto file_closer = at_scope_exit([&] { + if (std_in_fd >= 0) { + internal_close(std_in_fd); + } + if (std_out_fd >= 0) { + internal_close(std_out_fd); + } + if (std_err_fd >= 0) { + internal_close(std_err_fd); + } + }); + + if (!FileExists(program)) { + Report("WARNING: Program %s not found!\n", program); + return -1; + } + + int pid = internal_fork(); + + if (pid < 0) { + int rverrno; + if (internal_iserror(pid, &rverrno)) { + Report("WARNING: failed to fork (errno %d)\n", rverrno); + } + return pid; + } + + if (pid == 0) { + // Child subprocess + if (std_in_fd >= 0) { + internal_close(STDIN_FILENO); + internal_dup2(std_in_fd, STDIN_FILENO); + internal_close(std_in_fd); + } + if (std_out_fd >= 0) { + internal_close(STDOUT_FILENO); + internal_dup2(std_out_fd, STDOUT_FILENO); + internal_close(std_out_fd); + } + if (std_err_fd >= 0) { + internal_close(STDERR_FILENO); + internal_dup2(std_err_fd, STDERR_FILENO); + internal_close(std_err_fd); + } + + for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--) internal_close(fd); + + internal_execve(program, argv, nullptr); + internal__exit(1); + } + + return pid; +} + +bool IsProcessRunning(int pid) { + int process_status; + uptr waitpid_status = internal_waitpid(pid, &process_status, WNOHANG); + int local_errno; + if (internal_iserror(waitpid_status, &local_errno)) { + VReport(1, "Waiting on the process failed (errno %d).\n", local_errno); + return false; + } + return waitpid_status == 0; +} + #endif // SANITIZER_LINUX } // namespace __sanitizer |