Index: src/ccache/execute.cpp =================================================================== --- src/ccache/execute.cpp.orig 2025-05-31 14:52:32.000000000 +0000 +++ src/ccache/execute.cpp 2025-05-31 15:16:46.000000000 +0000 @@ -297,6 +297,7 @@ // Execute a compiler backend, capturing all output to the given paths the full // path to the compiler to run is in argv[0]. +# ifdef HAVE_SPAWN_H int execute(Context& ctx, const char* const* argv, @@ -372,6 +373,58 @@ return WEXITSTATUS(status); } +# else // !HAVE_SPAWN_H +int +execute(Context& ctx, + const char* const* argv, + util::Fd&& fd_out, + util::Fd&& fd_err) +{ + LOG("Executing {}", util::format_argv_for_logging(argv)); + + { + SignalHandlerBlocker signal_handler_blocker; + ctx.compiler_pid = fork(); + } + + if (ctx.compiler_pid == -1) { + throw core::Fatal(FMT("Failed to fork: {}", strerror(errno))); + } + + if (ctx.compiler_pid == 0) { + // Child. + dup2(*fd_out, STDOUT_FILENO); + fd_out.close(); + dup2(*fd_err, STDERR_FILENO); + fd_err.close(); + exit(execv(argv[0], const_cast(argv))); + } + + fd_out.close(); + fd_err.close(); + + int status; + int result; + + while ((result = waitpid(ctx.compiler_pid, &status, 0)) != ctx.compiler_pid) { + if (result == -1 && errno == EINTR) { + continue; + } + throw core::Fatal(FMT("waitpid failed: {}", strerror(errno))); + } + + { + SignalHandlerBlocker signal_handler_blocker; + ctx.compiler_pid = 0; + } + + if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { + return -1; + } + + return WEXITSTATUS(status); +} +# endif // !HAVE_SPAWN_H void execute_noreturn(const char* const* argv, const fs::path& /*temp_dir*/)