Merge pull request #14998 from NixOS/fix-remote-store-nar-from-path

libstore: Do not mark connections as bad when RemoteStore::narFromPath is called as a coroutine
This commit is contained in:
Eelco Dolstra
2026-01-20 16:08:07 +00:00
committed by GitHub
4 changed files with 28 additions and 10 deletions

View File

@@ -58,8 +58,13 @@ RemoteStore::RemoteStore(const Config & config)
ref<RemoteStore::Connection> RemoteStore::openConnectionWrapper()
{
if (failed)
if (failed) {
checkInterrupt();
/* Throw Interrupted instead of the following error to silence pesky
warning messages that ThreadPool prints on shutdown if other threads
failed. */
throw Error("opening a connection to remote store '%s' previously failed", config.getHumanReadableURI());
}
try {
return openConnection();
} catch (...) {

View File

@@ -44,8 +44,8 @@ public:
void operator=(AutoCloseFD pid);
#endif
~Pid();
int kill();
int wait();
int kill(bool allowInterrupts = true);
int wait(bool allowInterrupts = true);
// TODO: Implement for Windows
#ifndef _WIN32

View File

@@ -412,7 +412,7 @@ std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun, std::funct
}
if (cur.empty()) {
if (hasCoro) {
if (hasCoro && *coro) {
(*coro)();
}
if (*coro) {
@@ -427,6 +427,16 @@ std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun, std::funct
size_t n = cur.copy(data, len);
cur.remove_prefix(n);
/* This is necessary to ensure that the coroutine gets resumed
after the consumer has finished reading the Source. Otherwise the
coroutine is always abandoned (i.e. it is always destroyed when
suspended). */
if (cur.empty() && coro && *coro) {
(*coro)();
if (*coro)
cur = coro->get();
}
return n;
}
};

View File

@@ -41,9 +41,11 @@ Pid::Pid(pid_t pid)
}
Pid::~Pid()
{
try {
if (pid != -1)
kill();
kill(/*allowInterrupts=*/false);
} catch (...) {
ignoreExceptionInDestructor();
}
void Pid::operator=(pid_t pid)
@@ -59,7 +61,7 @@ Pid::operator pid_t()
return pid;
}
int Pid::kill()
int Pid::kill(bool allowInterrupts)
{
assert(pid != -1);
@@ -78,10 +80,10 @@ int Pid::kill()
logError(SysError("killing process %d", pid).info());
}
return wait();
return wait(allowInterrupts);
}
int Pid::wait()
int Pid::wait(bool allowInterrupts)
{
assert(pid != -1);
while (1) {
@@ -93,7 +95,8 @@ int Pid::wait()
}
if (errno != EINTR)
throw SysError("cannot get exit status of PID %d", pid);
checkInterrupt();
if (allowInterrupts)
checkInterrupt();
}
}