int RunSubProcess()

in tools/common/process.cc [145:191]


int RunSubProcess(const std::vector<std::string> &args,
                  std::ostream *stderr_stream, bool stdout_to_stderr) {
  std::vector<const char *> exec_argv = ConvertToCArgs(args);

  // Set up a pipe to redirect stderr from the child process so that we can
  // capture it and return it in the response message.
  std::unique_ptr<PosixSpawnIORedirector> redirector =
      PosixSpawnIORedirector::Create(stdout_to_stderr);
  if (!redirector) {
    (*stderr_stream) << "Error creating stderr pipe for child process.\n";
    return 254;
  }

  pid_t pid;
  int status =
      posix_spawn(&pid, args[0].c_str(), redirector->PosixSpawnFileActions(),
                  nullptr, const_cast<char **>(exec_argv.data()), environ);
  redirector->ConsumeAllSubprocessOutput(stderr_stream);

  if (status == 0) {
    int wait_status;
    do {
      wait_status = waitpid(pid, &status, 0);
    } while ((wait_status == -1) && (errno == EINTR));

    if (wait_status < 0) {
      std::cerr << "Error waiting on child process '" << args[0] << "'. "
                << strerror(errno) << "\n";
      return wait_status;
    }

    if (WIFEXITED(status)) {
      return WEXITSTATUS(status);
    }

    if (WIFSIGNALED(status)) {
      return WTERMSIG(status);
    }

    // Unhandled case, if we hit this we should handle it above.
    return 42;
  } else {
    std::cerr << "Error forking process '" << args[0] << "'. "
              << strerror(status) << "\n";
    return status;
  }
}