diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 305da4466..b07c71f6a 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -58,8 +58,13 @@ RemoteStore::RemoteStore(const Config & config) ref 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 (...) { diff --git a/src/libutil/include/nix/util/processes.hh b/src/libutil/include/nix/util/processes.hh index 23dee8713..141079e74 100644 --- a/src/libutil/include/nix/util/processes.hh +++ b/src/libutil/include/nix/util/processes.hh @@ -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 diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index e930a1964..b1ec76f32 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -412,7 +412,7 @@ std::unique_ptr sinkToSource(std::function fun, std::funct } if (cur.empty()) { - if (hasCoro) { + if (hasCoro && *coro) { (*coro)(); } if (*coro) { @@ -427,6 +427,16 @@ std::unique_ptr sinkToSource(std::function 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; } }; diff --git a/src/libutil/unix/processes.cc b/src/libutil/unix/processes.cc index 9582ff840..66423f011 100644 --- a/src/libutil/unix/processes.cc +++ b/src/libutil/unix/processes.cc @@ -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(); } }