#include <folly/io/Cursor.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/Stdlib.h>
+#include <folly/portability/SysSyscall.h>
#include <folly/portability/Unistd.h>
constexpr int kExecFailure = 127;
// Call c_str() here, as it's not necessarily safe after fork.
const char* childDir =
options.childDir_.empty() ? nullptr : options.childDir_.c_str();
- pid_t pid = vfork();
+
+ pid_t pid;
+#ifdef __linux__
+ if (options.cloneFlags_) {
+ pid = syscall(SYS_clone, *options.cloneFlags_, 0, nullptr, nullptr);
+ checkUnixError(pid, errno, "clone");
+ } else {
+#endif
+ pid = vfork();
+ checkUnixError(pid, errno, "vfork");
+#ifdef __linux__
+ }
+#endif
if (pid == 0) {
int errnoValue = prepareChild(options, &oldSignals, childDir);
if (errnoValue != 0) {
// If we get here, exec() failed.
childError(errFd, kExecFailure, errnoValue);
}
- // In parent. Make sure vfork() succeeded.
- checkUnixError(pid, errno, "vfork");
// Child is alive. We have to be very careful about throwing after this
// point. We are inside the constructor, so if we throw the Subprocess
throw SubprocessSpawnError(executable, info.errCode, info.errnoValue);
}
-ProcessReturnCode Subprocess::poll() {
+ProcessReturnCode Subprocess::poll(struct rusage* ru) {
returnCode_.enforce(ProcessReturnCode::RUNNING);
DCHECK_GT(pid_, 0);
int status;
- pid_t found = ::waitpid(pid_, &status, WNOHANG);
+ pid_t found = ::wait4(pid_, &status, WNOHANG, ru);
// The spec guarantees that EINTR does not occur with WNOHANG, so the only
// two remaining errors are ECHILD (other code reaped the child?), or
// EINVAL (cosmic rays?), both of which merit an abort: