|
|
@@ -27,6 +27,15 @@ void check_rc(bool b, std::string_view s) { |
|
|
|
|
|
|
|
::pid_t |
|
|
|
spawn_child(const std::vector<std::string>& command, int stdout_pipe, int close_me) noexcept { |
|
|
|
// We must allocate BEFORE fork(), since the CRT might stumble with malloc()-related locks that |
|
|
|
// are held during the fork(). |
|
|
|
std::vector<const char*> strings; |
|
|
|
strings.reserve(command.size() + 1); |
|
|
|
for (auto& s : command) { |
|
|
|
strings.push_back(s.data()); |
|
|
|
} |
|
|
|
strings.push_back(nullptr); |
|
|
|
|
|
|
|
auto child_pid = ::fork(); |
|
|
|
if (child_pid != 0) { |
|
|
|
return child_pid; |
|
|
@@ -38,25 +47,19 @@ spawn_child(const std::vector<std::string>& command, int stdout_pipe, int close_ |
|
|
|
rc = dup2(stdout_pipe, STDERR_FILENO); |
|
|
|
check_rc(rc != -1, "Failed to dup2 stderr"); |
|
|
|
|
|
|
|
std::vector<const char*> strings; |
|
|
|
strings.reserve(command.size() + 1); |
|
|
|
for (auto& s : command) { |
|
|
|
strings.push_back(s.data()); |
|
|
|
} |
|
|
|
strings.push_back(nullptr); |
|
|
|
::execvp(strings[0], (char* const*)strings.data()); |
|
|
|
|
|
|
|
if (errno == ENOENT) { |
|
|
|
std::cerr |
|
|
|
<< fmt::format("[dds child executor] The requested executable ({}) could not be found.", |
|
|
|
strings[0]); |
|
|
|
std::exit(-1); |
|
|
|
std::quick_exit(-1); |
|
|
|
} |
|
|
|
|
|
|
|
std::cerr << "[dds child executor] execvp returned! This is a fatal error: " |
|
|
|
<< std::system_category().message(errno) << '\n'; |
|
|
|
|
|
|
|
std::terminate(); |
|
|
|
std::quick_exit(-1); |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace |