nix/daemon: wrap kj stdio forwarding errors nicely

not doing this has lix crash if stdio forwarding fails for odd reasons,
such as ssh failing to set up a connection due to transient dns errors.

cf #1148

Change-Id: I543b7444236e69d3c13b47fb6c6eb37c65b96763
This commit is contained in:
eldritch horrors
2026-03-05 21:43:52 +00:00
parent 981dd6e9b2
commit c914b9fc53
2 changed files with 39 additions and 4 deletions
+13 -4
View File
@@ -34,7 +34,9 @@
#include <cstdint>
#include <cstring>
#include <exception>
#include <kj/async.h>
#include <kj/exception.h>
#include <string>
#include <unistd.h>
#include <signal.h>
@@ -536,13 +538,20 @@ static void forwardStdioConnection(AsyncIoRoot & aio, RemoteStore & store)
aio.blockOn(connSocket->pumpTo(*asyncStdout)
.then([](auto) -> Result<void> {
return {
std::make_exception_ptr(EndOfFile("unexpected EOF from daemon socket"))
};
return {std::make_exception_ptr(EndOfFile("unexpected EOF from daemon socket"))};
})
.exclusiveJoin(asyncStdin->pumpTo(*connSocket).then([](auto) -> Result<void> {
return result::success();
})));
}))
.catch_([](kj::Exception && e) -> Result<void> {
if (e.getType() == kj::Exception::Type::DISCONNECTED) {
return std::make_exception_ptr(Error("peer disconnected unexpectedly"));
} else {
return std::make_exception_ptr(
Error("forwarding daemon connection: %s", e.getDescription().cStr())
);
}
}));
}
/**
+26
View File
@@ -0,0 +1,26 @@
from pathlib import Path
from testlib.fixtures.nix import Nix
from testlib.fixtures.file_helper import with_files
from testlib.utils import get_global_asset_pack
@with_files(get_global_asset_pack("simple-drv"))
def test_stdio_forward_failure(nix: Nix, files: Path):
result = (
nix.nix_build(
[
f"{files}/simple.nix",
"--builders",
# build-remote handles the first ssh-ng in-process, but we want to test how nix-daemon
# behaves in error cases. we need to explicitly set remote-program for the main remote
# connection since we may choose the wrong binary otherwise. the inner ssh-ng also has
# a remote-program set to cause predictable failures (rather than using ssh impurely).
f"ssh-ng://localhost?remote-program={nix.env.dirs.nix_bin_dir}/nix-daemon&remote-store=ssh-ng://localhost?remote-program=false",
"-j0",
]
)
.run()
.expect(1)
)
assert "stream ended unexpectedly" in result.stderr_plain
assert "Lix crashed" not in result.stderr_plain