libstore: work around capnp fd passing bug

capnp does not handle fd passing correctly in all circumstances. we hit
such cirumstances when passing large closures path lists to build-hook.
since capnp seems to ignore fds passed in non-final segments of any rpc
message we just ensure that the capability including the log fd will be
small enough to not be fragmented on the receiving side of the channel.

cf https://github.com/capnproto/capnproto/issues/2359

Change-Id: Id22309264936b3a57bcc68a0753c3bfb3c9a43d2
This commit is contained in:
eldritch horrors
2025-07-23 13:53:24 +00:00
parent 2c6542bd9c
commit 43d6a79863
3 changed files with 14 additions and 7 deletions
+11 -4
View File
@@ -213,11 +213,18 @@ struct AcceptedBuild final : rpc::build_remote::HookInstance::AcceptedBuild::Ser
ref<Store> store;
StorePath drvPath;
BuilderConnection builder;
rpc::build_remote::HookInstance::BuildLogger::Client buildLogger;
AcceptedBuild(ref<Store> store, StorePath drvPath, BuilderConnection builder)
AcceptedBuild(
ref<Store> store,
StorePath drvPath,
BuilderConnection builder,
rpc::build_remote::HookInstance::BuildLogger::Client buildLogger
)
: store(store)
, drvPath(drvPath)
, builder(std::move(builder))
, buildLogger(std::move(buildLogger))
{
}
@@ -382,6 +389,7 @@ kj::Promise<void> Instance::build(BuildContext context)
auto drvPath = from(context.getParams().getDrvPath(), *store);
auto requiredFeatures =
rpc::to<std::set<std::string>>(context.getParams().getRequiredFeatures());
auto buildLogger = context.getParams().getBuildLogger();
auto result = TRY_AWAIT(connectToBuilder(
store, drvPath, machines, maxBuildJobs, amWilling, neededSystem, requiredFeatures
@@ -403,7 +411,7 @@ kj::Promise<void> Instance::build(BuildContext context)
auto ac = context.getResults().initResult().initGood().initAccept();
RPC_FILL(ac, setMachineName, builder->storeUri);
ac.setMachine(kj::heap<AcceptedBuild>(store, drvPath, std::move(*builder)));
ac.setMachine(kj::heap<AcceptedBuild>(store, drvPath, std::move(*builder), buildLogger));
} catch (...) {
RPC_FILL(context.getResults(), initResult, std::current_exception());
}
@@ -412,8 +420,7 @@ kj::Promise<void> Instance::build(BuildContext context)
kj::Promise<void> AcceptedBuild::run(RunContext context)
{
try {
auto builderLogger = context.getParams().getBuildLogger();
const int logFD = (co_await builderLogger.getFd()).orDefault(-1);
const int logFD = (co_await buildLogger.getFd()).orDefault(-1);
if (logFD < 0) {
throw Error("build-hook needs a logFD from the builder to build");
}
+1 -1
View File
@@ -1085,6 +1085,7 @@ try {
RPC_FILL(buildReq, setNeededSystem, drv->platform);
RPC_FILL(buildReq, initDrvPath, drvPath, worker.store);
RPC_FILL(buildReq, initRequiredFeatures, parsedDrv->getRequiredSystemFeatures());
buildReq.setBuildLogger(kj::heap<BuildHookLogger>(std::move(logPipe.writeSide)));
auto buildRespPromise = buildReq.send();
auto buildResp = TRY_AWAIT_RPC(buildRespPromise);
@@ -1112,7 +1113,6 @@ try {
/* Tell the hook all the inputs that have to be copied to the
remote system. */
RPC_FILL(runReq, initInputs, inputPaths, worker.store);
runReq.setBuildLogger(kj::heap<BuildHookLogger>(std::move(logPipe.writeSide)));
/* Tell the hooks the missing outputs that have to be copied back
from the remote system. */
+2 -2
View File
@@ -16,7 +16,6 @@ interface HookInstance {
run @0 (
inputs :List(StoreTypes.StorePath), # actual a set
wantedOutputs :List(Data), # actually StringSet
buildLogger :BuildLogger,
) -> (result :Types.ResultV);
}
@@ -36,6 +35,7 @@ interface HookInstance {
amWilling :Bool,
neededSystem :Data,
drvPath :StoreTypes.StorePath,
requiredFeatures :List(Data)
requiredFeatures :List(Data),
buildLogger :BuildLogger,
) -> (result :Types.Result(BuildResponse));
}