summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_linux_libcdep.cc
diff options
context:
space:
mode:
authorMike Aizatsky <aizatsky@chromium.org>2016-01-25 19:43:52 +0000
committerMike Aizatsky <aizatsky@chromium.org>2016-01-25 19:43:52 +0000
commite5b34d5a2bf4c882bc647dd26a8cea2adc76f63c (patch)
treee639ca0a5205bb8c229aeb5489e05fae12ba330f /lib/sanitizer_common/sanitizer_linux_libcdep.cc
parentaa7bb0678b43fddff39583510a9a665c447d0b47 (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.cc68
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