From 43d6a79863d5e28b6a2cd98ecb22fe4ff491057e Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Wed, 23 Jul 2025 15:12:03 +0200 Subject: [PATCH] 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 --- lix/legacy/build-remote.cc | 15 +++++++++++---- lix/libstore/build/derivation-goal.cc | 2 +- lix/libstore/build/hook-instance.capnp | 4 ++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lix/legacy/build-remote.cc b/lix/legacy/build-remote.cc index 48f8eed2b..c90e3f77e 100644 --- a/lix/legacy/build-remote.cc +++ b/lix/legacy/build-remote.cc @@ -213,11 +213,18 @@ struct AcceptedBuild final : rpc::build_remote::HookInstance::AcceptedBuild::Ser ref store; StorePath drvPath; BuilderConnection builder; + rpc::build_remote::HookInstance::BuildLogger::Client buildLogger; - AcceptedBuild(ref store, StorePath drvPath, BuilderConnection builder) + AcceptedBuild( + ref 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 Instance::build(BuildContext context) auto drvPath = from(context.getParams().getDrvPath(), *store); auto requiredFeatures = rpc::to>(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 Instance::build(BuildContext context) auto ac = context.getResults().initResult().initGood().initAccept(); RPC_FILL(ac, setMachineName, builder->storeUri); - ac.setMachine(kj::heap(store, drvPath, std::move(*builder))); + ac.setMachine(kj::heap(store, drvPath, std::move(*builder), buildLogger)); } catch (...) { RPC_FILL(context.getResults(), initResult, std::current_exception()); } @@ -412,8 +420,7 @@ kj::Promise Instance::build(BuildContext context) kj::Promise 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"); } diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index b93f851d3..46da79d6e 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -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(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(std::move(logPipe.writeSide))); /* Tell the hooks the missing outputs that have to be copied back from the remote system. */ diff --git a/lix/libstore/build/hook-instance.capnp b/lix/libstore/build/hook-instance.capnp index 81c8e962a..05840e8d5 100644 --- a/lix/libstore/build/hook-instance.capnp +++ b/lix/libstore/build/hook-instance.capnp @@ -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)); }