fix(process): report Linux exec failures

This commit is contained in:
2026-06-18 19:31:03 -05:00
parent bf56b43190
commit 1b7f813094

View File

@@ -6,6 +6,7 @@
#include <izo/system.hpp>
#include <dlfcn.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
@@ -75,19 +76,42 @@ std::filesystem::path get_known_path(known_path path, std::string* error_message
process_result launch_process(const process_options& options) {
if (options.executable.empty()) return {false, 0, "Executable path is required"};
int error_pipe[2];
if (pipe2(error_pipe, O_CLOEXEC) != 0) return {false, 0, std::strerror(errno)};
const pid_t child = fork();
if (child < 0) return {false, 0, std::strerror(errno)};
if (child < 0) {
const std::string error = std::strerror(errno);
close(error_pipe[0]);
close(error_pipe[1]);
return {false, 0, error};
}
if (child == 0) {
close(error_pipe[0]);
if (options.detached) setsid();
if (!options.working_directory.empty() && chdir(options.working_directory.c_str()) != 0) _exit(126);
if (!options.working_directory.empty() && chdir(options.working_directory.c_str()) != 0) {
const int error = errno;
write(error_pipe[1], &error, sizeof(error));
_exit(126);
}
std::vector<std::string> values{options.executable.string()};
values.insert(values.end(), options.arguments.begin(), options.arguments.end());
std::vector<char*> argv;
for (auto& value : values) argv.push_back(value.data());
argv.push_back(nullptr);
execvp(argv[0], argv.data());
const int error = errno;
write(error_pipe[1], &error, sizeof(error));
_exit(127);
}
close(error_pipe[1]);
int child_error = 0;
const ssize_t error_bytes = read(error_pipe[0], &child_error, sizeof(child_error));
close(error_pipe[0]);
if (error_bytes > 0) {
int status = 0;
while (waitpid(child, &status, 0) < 0 && errno == EINTR) {}
return {false, 0, std::strerror(child_error)};
}
std::thread([child] {
int status = 0;
while (waitpid(child, &status, 0) < 0 && errno == EINTR) {}