]> sourceware.org Git - systemtap.git/commitdiff
Use posix_spawn_file_actions for stap_system_read
authorJosh Stone <jistone@redhat.com>
Fri, 11 Feb 2011 00:43:55 +0000 (16:43 -0800)
committerJosh Stone <jistone@redhat.com>
Fri, 11 Feb 2011 00:43:55 +0000 (16:43 -0800)
The file actions can handle the dup2 necessary to hook a pipe onto the
child's stdout.  It could do the necessary closing too, but we'll just
use FD_CLOEXEC for that.

* util.cxx (stap_spawn): Take file_actions for the posix_spawn.
  (pipe_child_fd): New, open a pipe and set the dup2 action for it.
  (stap_system_read): Let stap_spawn and pipe_child_fd do the hard part.

util.cxx

index fe4d5c0381be352634d3ea26f0cc4d41b1c28e8f..db11514d1422695089e07c51ef7453a9b293dfc1 100644 (file)
--- a/util.cxx
+++ b/util.cxx
@@ -450,9 +450,27 @@ stap_waitpid(int verbose, pid_t pid)
   return ret;
 }
 
+static int
+pipe_child_fd(posix_spawn_file_actions_t* fa, int pipefd[2], int childfd)
+{
+  if (pipe(pipefd))
+    return -1;
+
+  int dir = childfd ? 1 : 0;
+  if (!fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) &&
+      !fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) &&
+      !posix_spawn_file_actions_adddup2(fa, pipefd[dir], childfd))
+    return 0;
+
+  close(pipefd[0]);
+  close(pipefd[1]);
+  return -1;
+}
+
 // Runs a command with a saved PID, so we can kill it from the signal handler
-pid_t
-stap_spawn(int verbose, const std::string& command)
+static pid_t
+stap_spawn(int verbose, const std::string& command,
+           posix_spawn_file_actions_t* fa)
 {
   const char *cmd = command.c_str();
   char const * const argv[] = { "sh", "-c", cmd, NULL };
@@ -463,7 +481,7 @@ stap_spawn(int verbose, const std::string& command)
   if (verbose > 1)
     clog << "Running " << command << endl;
 
-  ret = posix_spawn(&pid, "/bin/sh", NULL, NULL,
+  ret = posix_spawn(&pid, "/bin/sh", fa, NULL,
                     const_cast<char * const *>(argv), environ);
   PROBE2(stap, stap_system__spawn, ret, pid);
   if (ret != 0)
@@ -477,6 +495,13 @@ stap_spawn(int verbose, const std::string& command)
   return pid;
 }
 
+// The API version of stap_spawn doesn't expose file_actions, for now.
+pid_t
+stap_spawn(int verbose, const std::string& command)
+{
+  return stap_spawn(verbose, command, NULL);
+}
+
 // Runs a command with a saved PID, so we can kill it from the signal handler,
 // and wait for it to finish.
 int
@@ -498,40 +523,33 @@ stap_system(int verbose, const std::string& command)
 int
 stap_system_read(int verbose, const string& command, ostream& out)
 {
-  int ret, pfd[2];
+  posix_spawn_file_actions_t fa;
+  if (posix_spawn_file_actions_init(&fa) != 0)
+    return -1;
 
-  ret = pipe(pfd);
-  if (ret != 0)
+  // remap the write fd to the child's stdout
+  int ret = -1, pfd[2];
+  if (pipe_child_fd(&fa, pfd, 1) == 0)
     {
-      return -1;
-    }
+      pid_t child = stap_spawn(verbose, command, &fa);
+      if (child > 0)
+        {
+          // read everything from the child
+          stdio_filebuf<char> in(pfd[0], ios_base::in);
+          close(pfd[1]);
+          out << &in;
 
-  pid_t child = fork();
-  if (child < 0)
-    {
-      return -1;
-    }
-  else if (child == 0)
-    {
-      // remap the write fd to stdout
-      dup2(pfd[1], 1);
-      close(pfd[0]);
-      close(pfd[1]);
-
-      // exec the desired command
-      char const * const argv[] = { "sh", "-c", command.c_str(), NULL };
-      ret = execv("/bin/sh", const_cast<char * const *>(argv));
-      exit(ret); // only reached on exec error
+          ret = stap_waitpid(verbose, child);
+        }
+      else
+        {
+          close(pfd[0]);
+          close(pfd[1]);
+        }
     }
-  else
-    spawned_pids.insert(child);
-
-  // read everything from the child
-  stdio_filebuf<char> in(pfd[0], ios_base::in);
-  close(pfd[1]);
-  out << &in;
 
-  return stap_waitpid(verbose, child);
+  posix_spawn_file_actions_destroy(&fa);
+  return ret;
 }
 
 
This page took 0.029739 seconds and 5 git commands to generate.