diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index a162df1ad..59fc75ed0 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -594,10 +594,24 @@ struct curlFileTransfer : public FileTransfer } }; - bool quit = false; std:: priority_queue, std::vector>, EmbargoComparator> incoming; + private: + bool quitting = false; + public: + void quit() + { + quitting = true; + /* We wil not be processing any more incomming requests */ + while (!incoming.empty()) + incoming.pop(); + } + + bool isQuitting() + { + return quitting; + } }; Sync state_; @@ -649,7 +663,7 @@ struct curlFileTransfer : public FileTransfer /* Signal the worker thread to exit. */ { auto state(state_.lock()); - state->quit = true; + state->quit(); } #ifndef _WIN32 // TODO need graceful async exit support on Windows? writeFull(wakeupPipe.writeSide.get(), " ", false); @@ -750,7 +764,7 @@ struct curlFileTransfer : public FileTransfer break; } } - quit = state->quit; + quit = state->isQuitting(); } for (auto & item : incoming) { @@ -767,18 +781,20 @@ struct curlFileTransfer : public FileTransfer void workerThreadEntry() { + // Unwinding or because someone called `quit`. + bool normalExit = true; try { workerThreadMain(); } catch (nix::Interrupted & e) { + normalExit = false; } catch (std::exception & e) { printError("unexpected error in download thread: %s", e.what()); + normalExit = false; } - { + if (!normalExit) { auto state(state_.lock()); - while (!state->incoming.empty()) - state->incoming.pop(); - state->quit = true; + state->quit(); } } @@ -789,7 +805,7 @@ struct curlFileTransfer : public FileTransfer { auto state(state_.lock()); - if (state->quit) + if (state->isQuitting()) throw nix::Error("cannot enqueue download request because the download thread is shutting down"); state->incoming.push(item); } @@ -845,7 +861,7 @@ ref getFileTransfer() { static ref fileTransfer = makeCurlFileTransfer(); - if (fileTransfer->state_.lock()->quit) + if (fileTransfer->state_.lock()->isQuitting()) fileTransfer = makeCurlFileTransfer(); return fileTransfer;