diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index 86feec53f..249cb0e8c 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -250,7 +250,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 7d352b65c..5896e3a55 100644 --- a/lix/libfetchers/git.cc +++ b/lix/libfetchers/git.cc @@ -759,7 +759,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 a50aa4553..c223b4cc9 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -990,7 +990,7 @@ void runPostBuildHook( .captureStdout = true, .mergeStderrToStdout = true, }); - Finally const _wait([&] { proc.wait(); }); + Finally const _wait([&] { proc.waitAndCheck(); }); // FIXME just process the data, without a wrapper sink class proc.getStdout()->drainInto(sink); diff --git a/lix/libutil/processes.cc b/lix/libutil/processes.cc index 4532ae6b9..bc4433c19 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(); }; };