[compiler-rt] r258710 - [sanitizers] extracted process management functions

Mike Aizatsky via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 25 11:43:52 PST 2016


Author: aizatsky
Date: Mon Jan 25 13:43:52 2016
New Revision: 258710

URL: http://llvm.org/viewvc/llvm-project?rev=258710&view=rev
Log:
[sanitizers] extracted process management functions

Differential Revision: http://reviews.llvm.org/D16542

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.cc Mon Jan 25 13:43:52 2016
@@ -423,6 +423,10 @@ bool TemplateMatch(const char *templ, co
 static const char kPathSeparator = SANITIZER_WINDOWS ? ';' : ':';
 
 char *FindPathToBinary(const char *name) {
+  if (FileExists(name)) {
+    return internal_strdup(name);
+  }
+
   const char *path = GetEnv("PATH");
   if (!path)
     return nullptr;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Mon Jan 25 13:43:52 2016
@@ -279,6 +279,15 @@ const char *GetPwd();
 char *FindPathToBinary(const char *name);
 bool IsPathSeparator(const char c);
 bool IsAbsolutePath(const char *path);
+// Starts a subprocess and returs its pid.
+// If *_fd parameters are >=0 their corresponding input/output
+// streams would be redirect to the file. The files would always be closed
+// in parent process even in case of an error.
+int StartSubprocess(const char *program, char *const argv[],
+                    fd_t std_in_fd = kInvalidFd, fd_t std_out_fd = kInvalidFd,
+                    fd_t std_err_fd = kInvalidFd);
+// Checks if specified process is still running
+bool IsProcessRunning(int pid);
 
 u32 GetUid();
 void ReExec();
@@ -748,6 +757,20 @@ void GetPcSpBp(void *context, uptr *pc,
 void DisableReexec();
 void MaybeReexec();
 
+template <typename Fn>
+struct AutoRunner {
+  explicit AutoRunner(Fn fn) : fn_(fn) {}
+  ~AutoRunner() { fn_(); }
+  Fn fn_;
+};
+
+// A simple scope guard. Usage:
+// auto cleanup = at_scope_exit([]{ do_cleanup; });
+template <typename Fn>
+AutoRunner<Fn> at_scope_exit(Fn fn) {
+  return AutoRunner<Fn>(fn);
+}
+
 }  // namespace __sanitizer
 
 inline void *operator new(__sanitizer::operator_new_size_type size,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h Mon Jan 25 13:43:52 2016
@@ -43,6 +43,8 @@ uptr internal_prctl(int option, uptr arg
 // internal_sigaction instead.
 int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
 void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
+uptr internal_execve(const char *filename, char *const argv[],
+                     char *const envp[]);
 #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \
   || defined(__powerpc64__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Mon Jan 25 13:43:52 2016
@@ -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

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Mon Jan 25 13:43:52 2016
@@ -670,6 +670,18 @@ char **GetArgv() {
   return *_NSGetArgv();
 }
 
+int StartSubprocess(const char *program, char *const argv[],
+                    fd_t std_in_fd = kInvalidFd, fd_t std_out_fd = kInvalidFd,
+                    fd_t std_err_fd = kInvalidFd) {
+  // FIXME: implement on this platform.
+  return -1;
+}
+
+bool IsProcessRunning(int pid) {
+  // FIXME: implement on this platform.
+  return false;
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc Mon Jan 25 13:43:52 2016
@@ -137,47 +137,23 @@ bool SymbolizerProcess::StartSymbolizerS
     CHECK(infd);
     CHECK(outfd);
 
-    // Real fork() may call user callbacks registered with pthread_atfork().
-    pid = internal_fork();
-    if (pid == -1) {
-      // Fork() failed.
+    const char *argv[kArgVMax];
+    GetArgV(path_, argv);
+    pid = StartSubprocess(path_, const_cast<char **>(&argv[0]),
+                          outfd[0] /* stdin */, infd[1] /* stdout */);
+    if (pid < 0) {
       internal_close(infd[0]);
-      internal_close(infd[1]);
       internal_close(outfd[0]);
-      internal_close(outfd[1]);
-      Report("WARNING: failed to fork external symbolizer "
-             " (errno: %d)\n", errno);
       return false;
-    } else if (pid == 0) {
-      // Child subprocess.
-      internal_close(STDOUT_FILENO);
-      internal_close(STDIN_FILENO);
-      internal_dup2(outfd[0], STDIN_FILENO);
-      internal_dup2(infd[1], STDOUT_FILENO);
-      internal_close(outfd[0]);
-      internal_close(outfd[1]);
-      internal_close(infd[0]);
-      internal_close(infd[1]);
-      for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)
-        internal_close(fd);
-      const char *argv[kArgVMax];
-      GetArgV(path_, argv);
-      execv(path_, const_cast<char **>(&argv[0]));
-      internal__exit(1);
     }
 
-    // Continue execution in parent process.
-    internal_close(outfd[0]);
-    internal_close(infd[1]);
     input_fd_ = infd[0];
     output_fd_ = outfd[1];
   }
 
   // Check that symbolizer subprocess started successfully.
-  int pid_status;
   SleepForMillis(kSymbolizerStartupTimeMillis);
-  int exited_pid = waitpid(pid, &pid_status, WNOHANG);
-  if (exited_pid != 0) {
+  if (!IsProcessRunning(pid)) {
     // Either waitpid failed, or child has already exited.
     Report("WARNING: external symbolizer didn't start up correctly!\n");
     return false;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Mon Jan 25 13:43:52 2016
@@ -775,6 +775,18 @@ char **GetArgv() {
   return 0;
 }
 
+int StartSubprocess(const char *program, char *const argv[],
+                    fd_t std_in_fd = kInvalidFd, fd_t std_out_fd = kInvalidFd,
+                    fd_t std_err_fd = kInvalidFd) {
+  // FIXME: implement on this platform.
+  return -1;
+}
+
+bool IsProcessRunning(int pid) {
+  // FIXME: implement on this platform.
+  return false;
+}
+
 }  // namespace __sanitizer
 
 #endif  // _WIN32

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc?rev=258710&r1=258709&r2=258710&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc Mon Jan 25 13:43:52 2016
@@ -263,6 +263,29 @@ TEST(SanitizerLinux, ThreadSelfTest) {
 }
 #endif
 
+TEST(SanitizerCommon, StartSubprocessTest) {
+  int pipe_fds[2];
+  ASSERT_EQ(0, pipe(pipe_fds));
+  const char *argv[] = {"/bin/sh", "-c", "echo -n 'hello'"};
+  int pid = StartSubprocess("/bin/sh", const_cast<char **>(&argv[0]),
+                            kInvalidFd /* stdin */, pipe_fds[1] /* stdout */);
+  ASSERT_GT(pid, 0);
+
+  // wait for process to finish.
+  while (IsProcessRunning(pid)) {
+  }
+  ASSERT_FALSE(IsProcessRunning(pid));
+
+  char buffer[256];
+  char *ptr = buffer;
+  uptr bytes_read;
+  while (ReadFromFile(pipe_fds[0], ptr, 256, &bytes_read)) {
+    ptr += bytes_read;
+  }
+  ASSERT_EQ(0, memcmp(buffer, "hello", 5)) << "Buffer: " << buffer;
+  internal_close(pipe_fds[0]);
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_LINUX




More information about the llvm-commits mailing list