From 58b113d62332bb221b080af5c6d941fe5511e96f Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 17 Mar 2025 15:45:27 +0100 Subject: [PATCH] libutil: make RunningProgram more useful make it moveable, make it killable, and add a stdout fd accessor. Change-Id: I2387cbe8ac67b899a322cd6c7d306ef9ea7abcd0 --- lix/libcmd/repl.cc | 4 ++-- lix/libfetchers/git.cc | 2 +- lix/libstore/build/derivation-goal.cc | 2 +- lix/libutil/processes.cc | 19 +++++++++++++++++-- lix/libutil/processes.hh | 16 +++++++++++++++- 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index ae10e8eb4..2b5cfc866 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -254,7 +254,7 @@ void runNix(Path program, const Strings & args) .program = settings.nixBinDir+ "/" + program, .args = args, .environment = subprocessEnv, - }).wait(); + }).waitAndCheck(); return; } @@ -672,7 +672,7 @@ ProcessLineResult NixRepl::processLine(std::string line) // runProgram redirects stdout to a StringSink, // using runProgram2 to allow editors to display their UI - runProgram2(RunOptions { .program = editor, .searchPath = true, .args = args }).wait(); + runProgram2(RunOptions { .program = editor, .searchPath = true, .args = args }).waitAndCheck(); // Reload right after exiting the editor if path is not in store // Store is immutable, so there could be no changes, so there's no need to reload diff --git a/lix/libfetchers/git.cc b/lix/libfetchers/git.cc index 21fa1904d..462be82ab 100644 --- a/lix/libfetchers/git.cc +++ b/lix/libfetchers/git.cc @@ -766,7 +766,7 @@ struct GitInputScheme : InputScheme .args = { "-C", repoDir, "--git-dir", gitDir, "archive", input.getRev()->gitRev() }, .captureStdout = true, }); - Finally const _wait([&] { proc.wait(); }); + Finally const _wait([&] { proc.waitAndCheck(); }); unpackTarfile(*proc.getStdout(), tmpDir); } diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index f96cec1ed..c6c971709 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -1015,7 +1015,7 @@ void runPostBuildHook( }); Finally const _wait([&] { try { - proc.wait(); + proc.waitAndCheck(); } catch (nix::Error & e) { e.addTrace(nullptr, "while running the post-build-hook %s for derivation %s", diff --git a/lix/libutil/processes.cc b/lix/libutil/processes.cc index e2cc2515b..6b24d943f 100644 --- a/lix/libutil/processes.cc +++ b/lix/libutil/processes.cc @@ -249,7 +249,7 @@ std::pair runProgram(RunOptions && options) try { auto proc = runProgram2(options); - Finally const _wait([&] { proc.wait(); }); + Finally const _wait([&] { proc.waitAndCheck(); }); stdout = proc.getStdout()->drain(); } catch (ExecError & e) { status = e.status; @@ -277,7 +277,22 @@ RunningProgram::~RunningProgram() } } -void RunningProgram::wait() +std::tuple, int> RunningProgram::release() +{ + return {pid.release(), std::move(stdoutSource), stdout_.release()}; +} + +int RunningProgram::kill() +{ + return pid.kill(); +} + +int RunningProgram::wait() +{ + return pid.wait(); +} + +void RunningProgram::waitAndCheck() { if (std::uncaught_exceptions() == 0) { int status = pid.wait(); diff --git a/lix/libutil/processes.hh b/lix/libutil/processes.hh index e9e4eb15a..01c42b9fc 100644 --- a/lix/libutil/processes.hh +++ b/lix/libutil/processes.hh @@ -102,9 +102,23 @@ private: public: RunningProgram() = default; + RunningProgram(RunningProgram &&) = default; + RunningProgram & operator=(RunningProgram &&) = default; ~RunningProgram(); - void wait(); + explicit operator bool() const { return bool(pid); } + + std::tuple, int> release(); + + int kill(); + [[nodiscard]] + int wait(); + void waitAndCheck(); + + std::optional getStdoutFD() const + { + return stdout_ ? std::optional(stdout_.get()) : std::nullopt; + } Source * getStdout() const { return stdoutSource.get(); }; };