/*
- * 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.
#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>
// 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;
// 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
}
}
- // 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_) {
}
#endif
+ if (options.processGroupLeader_) {
+ if (setpgrp() == -1) {
+ return errno;
+ }
+ }
+
return 0;
}
char** argv, char** env,
const Options& options) const {
// Now, finally, exec.
- int r;
if (options.usePath_) {
::execvp(executable, argv);
} else {
} 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;
} // namespace
} // namespace folly
-