libstore: make build hook exit status reusable

this makes it possible to wait for the hook to exit in one place,
process its exit status for some purpose, and later process it in
another place for a different purpose. rpc will need this to shut
down a hook cleanly after the hook has completed its assignments.

Change-Id: I5af2d5aac4b02a0a200d720d0e6f0b5df5496aaf
This commit is contained in:
eldritch horrors
2025-10-19 16:09:32 +00:00
parent 7e171a4abe
commit 6c416ff2ca
3 changed files with 35 additions and 8 deletions
+1 -1
View File
@@ -792,7 +792,7 @@ void replaceValidPath(const Path & storePath, const Path & tmpPath)
int DerivationGoal::getChildStatus()
{
return hook->pid.kill();
return hook->kill();
}
void DerivationGoal::closeReadPipes()
+1 -1
View File
@@ -88,7 +88,7 @@ try {
HookInstance::~HookInstance()
{
try {
if (pid) pid.kill();
kill();
} catch (...) {
ignoreExceptionInDestructor();
}
+33 -6
View File
@@ -23,11 +23,6 @@ struct HookInstance
std::unique_ptr<capnp::TwoPartyClient> client;
rpc::build_remote::HookInstance::Client rpc;
/**
* The process ID of the hook.
*/
Pid pid;
std::map<ActivityId, Activity> activities;
static kj::Promise<Result<std::unique_ptr<HookInstance>>> create();
@@ -43,9 +38,41 @@ struct HookInstance
, conn(std::move(conn))
, client(std::move(client))
, rpc(std::move(rpc))
, pid(std::move(pid))
, pidOrStatus(std::move(pid))
{
}
~HookInstance();
int wait()
{
return childStatusOr<&Pid::wait>();
}
int kill()
{
return childStatusOr<&Pid::kill>();
}
private:
/**
* The process ID of the hook if it's running, or its exit status if not.
*/
std::variant<Pid, int> pidOrStatus;
template<int (Pid::*fn)()>
int childStatusOr()
{
return std::visit(
overloaded{
[&](Pid & pid) {
int status = (pid.*fn)();
pidOrStatus = status;
return status;
},
[](int status) { return status; },
},
pidOrStatus
);
}
};
}