in util/process_wrapper/system_posix.cc [121:195]
int System::Exec(const System::StrType &executable,
const System::Arguments &arguments,
const System::EnvironmentBlock &environment_block,
const StrType &stdout_file, const StrType &stderr_file) {
OutputPipe stdout_pipe;
if (!stdout_file.empty() && !stdout_pipe.CreateEnds()) {
return -1;
}
OutputPipe stderr_pipe;
if (!stderr_file.empty() && !stderr_pipe.CreateEnds()) {
return -1;
}
pid_t child_pid = fork();
if (child_pid < 0) {
std::cerr << "process wrapper error: failed to fork the current process: "
<< std::strerror(errno) << ".\n";
return -1;
} else if (child_pid == 0) {
if (!stdout_file.empty()) {
stdout_pipe.DupWriteEnd(STDOUT_FILENO);
}
if (!stderr_file.empty()) {
stderr_pipe.DupWriteEnd(STDERR_FILENO);
}
std::vector<char *> argv;
argv.push_back(const_cast<char *>(executable.c_str()));
for (const StrType &argument : arguments) {
argv.push_back(const_cast<char *>(argument.c_str()));
}
argv.push_back(nullptr);
std::vector<char *> envp;
for (const StrType &ev : environment_block) {
envp.push_back(const_cast<char *>(ev.c_str()));
}
envp.push_back(nullptr);
umask(022);
execve(executable.c_str(), argv.data(), envp.data());
std::cerr << "process wrapper error: failed to exec the new process: "
<< std::strerror(errno) << ".\n";
return -1;
}
if (!stdout_file.empty()) {
if (!stdout_pipe.WriteToFile(stdout_file)) {
return -1;
}
}
if (!stderr_file.empty()) {
if (!stderr_pipe.WriteToFile(stderr_file)) {
return -1;
}
}
int err, exit_status;
do {
err = waitpid(child_pid, &exit_status, 0);
} while (err == -1 && errno == EINTR);
if (WIFEXITED(exit_status)) {
return WEXITSTATUS(exit_status);
} else if (WIFSIGNALED(exit_status)) {
raise(WTERMSIG(exit_status));
} else if (WIFSTOPPED(exit_status)) {
raise(WSTOPSIG(exit_status));
} else {
std::cerr << "process wrapper error: failed to parse exit code of the "
"child process: "
<< exit_status << ".\n";
}
return -1;
}