diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index 0ca805b4d..0e8694a6d 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -294,7 +294,13 @@ std::vector Worker::run(std::function req) topGoals.insert(goal); } - auto promise = runImpl().exclusiveJoin(updateStatistics()); + auto onInterrupt = kj::newPromiseAndCrossThreadFulfiller>(); + auto interruptCallback = createInterruptCallback([&] { + return result::failure(std::make_exception_ptr(makeInterrupted())); + }); + + auto promise = + runImpl().exclusiveJoin(updateStatistics()).exclusiveJoin(std::move(onInterrupt.promise)); // TODO GC interface? if (auto localStore = dynamic_cast(&store); localStore && settings.minFree != 0) { @@ -316,9 +322,6 @@ try { debug("entered goal loop"); while (1) { - - checkInterrupt(); - if (topGoals.empty()) break; /* Wait for input. */ diff --git a/src/libutil/signals.cc b/src/libutil/signals.cc index 4e9ed0ba1..dac2964ae 100644 --- a/src/libutil/signals.cc +++ b/src/libutil/signals.cc @@ -12,13 +12,18 @@ std::atomic _isInterrupted = false; thread_local std::function interruptCheck; +Interrupted makeInterrupted() +{ + return Interrupted("interrupted by the user"); +} + void _interrupted() { /* Block user interrupts while an exception is being handled. Throwing an exception while another exception is being handled kills the program! */ if (!std::uncaught_exceptions()) { - throw Interrupted("interrupted by the user"); + throw makeInterrupted(); } } diff --git a/src/libutil/signals.hh b/src/libutil/signals.hh index 02f8d2ca3..538ff94b4 100644 --- a/src/libutil/signals.hh +++ b/src/libutil/signals.hh @@ -16,10 +16,13 @@ namespace nix { /* User interruption. */ +class Interrupted; + extern std::atomic _isInterrupted; extern thread_local std::function interruptCheck; +Interrupted makeInterrupted(); void _interrupted(); void inline checkInterrupt()