Telnet client
[folly.git] / folly / Subprocess.cpp
index ac8eab60d7a1423c8db0af85ef0b0998885c870b..36c824c3cfe2a773bcf1868c55ea4df952083a4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,7 +39,6 @@
 
 #include <folly/Conv.h>
 #include <folly/Exception.h>
-#include <folly/FileUtil.h>
 #include <folly/ScopeGuard.h>
 #include <folly/String.h>
 #include <folly/io/Cursor.h>
@@ -119,7 +118,7 @@ namespace {
 // Copy pointers to the given strings in a format suitable for posix_spawn
 std::unique_ptr<const char*[]> cloneStrings(const std::vector<std::string>& s) {
   std::unique_ptr<const char*[]> d(new const char*[s.size() + 1]);
-  for (int i = 0; i < s.size(); i++) {
+  for (size_t i = 0; i < s.size(); i++) {
     d[i] = s[i].c_str();
   }
   d[s.size()] = nullptr;
@@ -256,29 +255,25 @@ void Subprocess::spawn(
   // in case it fails before calling exec()
   int errFds[2];
 #if FOLLY_HAVE_PIPE2
-  int r = ::pipe2(errFds, O_CLOEXEC);
+  checkUnixError(::pipe2(errFds, O_CLOEXEC), "pipe2");
 #else
-  int r = ::pipe(errFds);
+  checkUnixError(::pipe(errFds), "pipe");
 #endif
-  checkUnixError(r, "pipe");
   SCOPE_EXIT {
     CHECK_ERR(::close(errFds[0]));
     if (errFds[1] >= 0) {
       CHECK_ERR(::close(errFds[1]));
     }
   };
-  // Ask the child to close the read end of the error pipe.
-  options.fdActions_[errFds[0]] = CLOSE;
 
 #if !FOLLY_HAVE_PIPE2
-  r = fcntl(errFds[0], F_SETFD, FD_CLOEXEC);
-  checkUnixError(r, "set FD_CLOEXEC");
+  // Ask the child to close the read end of the error pipe.
+  checkUnixError(fcntl(errFds[0], F_SETFD, FD_CLOEXEC), "set FD_CLOEXEC");
   // Set the close-on-exec flag on the write side of the pipe.
   // This way the pipe will be closed automatically in the child if execve()
   // succeeds.  If the exec fails the child can write error information to the
   // pipe.
-  r = fcntl(errFds[1], F_SETFD, FD_CLOEXEC);
-  checkUnixError(r, "set FD_CLOEXEC");
+  checkUnixError(fcntl(errFds[1], F_SETFD, FD_CLOEXEC), "set FD_CLOEXEC");
 #endif
 
   // Perform the actual work of setting up pipes then forking and
@@ -454,12 +449,9 @@ int Subprocess::prepareChild(const Options& options,
     }
   }
 
-  // Close parent's ends of all pipes
-  for (auto& p : pipes_) {
-    if (::close(p.parentFd) == -1) {
-      return errno;
-    }
-  }
+  // We don't have to explicitly close the parent's end of all pipes,
+  // as they all have the FD_CLOEXEC flag set and will be closed at
+  // exec time.
 
   // Close all fds that we're supposed to close.
   for (auto& p : options.fdActions_) {
@@ -494,6 +486,12 @@ int Subprocess::prepareChild(const Options& options,
   }
 #endif
 
+  if (options.processGroupLeader_) {
+    if (setpgrp() == -1) {
+      return errno;
+    }
+  }
+
   return 0;
 }
 
@@ -501,7 +499,6 @@ int Subprocess::runChild(const char* executable,
                          char** argv, char** env,
                          const Options& options) const {
   // Now, finally, exec.
-  int r;
   if (options.usePath_) {
     ::execvp(executable, argv);
   } else {
@@ -747,7 +744,7 @@ void Subprocess::communicate(FdCallback readCallback,
     } while (r == -1 && errno == EINTR);
     checkUnixError(r, "poll");
 
-    for (int i = 0; i < pipes_.size(); ++i) {
+    for (size_t i = 0; i < pipes_.size(); ++i) {
       auto& p = pipes_[i];
       DCHECK_EQ(fds[i].fd, p.parentFd);
       short events = fds[i].revents;
@@ -826,4 +823,3 @@ Initializer initializer;
 }  // namespace
 
 }  // namespace folly
-