// 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;
// child has exited and can be immediately waited for. In all other cases,
// we have no way of cleaning up the child.
+ if (options.processGroupLeader_) {
+ // This is done both in the parent and the child to avoid the race where
+ // the parent assumes that the child is a leader, but the child has not
+ // yet run setprp(). Not checking error codes since we're deliberately
+ // racing the child, which may already have run execve(), and expect to
+ // lose frequently.
+ setpgid(pid_, pid_);
+ }
// Close writable side of the errFd pipe in the parent process
CHECK_ERR(::close(errFds[1]));
errFds[1] = -1;
}
#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
-