diff --git a/doc/manual/rl-next/repl-interrupt.md b/doc/manual/rl-next/repl-interrupt.md new file mode 100644 index 000000000..61a8ab71e --- /dev/null +++ b/doc/manual/rl-next/repl-interrupt.md @@ -0,0 +1,8 @@ +--- +synopsis: Interrupting builds in the REPL works more than once +cls: 1097 +--- + +Builds in the REPL can be interrupted by pressing Ctrl+C. +Previously, this only worked once per REPL session; further attempts would be ignored. +This issue is now fixed, so that builds can be canceled consistently. diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 696bb3c12..34de2160a 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -262,6 +262,8 @@ ReplExitStatus NixRepl::mainLoop() std::string input; while (true) { + _isInterrupted = false; + // When continuing input from previous lines, don't print a prompt, just align to the same // number of chars as the prompt. if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) { @@ -424,8 +426,6 @@ ProcessLineResult NixRepl::processLine(std::string line) if (line.empty()) return ProcessLineResult::PromptAgain; - _isInterrupted = false; - std::string command, arg; if (line[0] == ':') { diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 9d4dd41ed..96ecbac8f 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -320,16 +320,7 @@ int handleExceptions(const std::string & programName, std::function fun) std::string error = ANSI_RED "error:" ANSI_NORMAL " "; try { - try { - fun(); - } catch (...) { - /* Subtle: we have to make sure that any `interrupted' - condition is discharged before we reach printMsg() - below, since otherwise it will throw an (uncaught) - exception. */ - setInterruptThrown(); - throw; - } + fun(); } catch (Exit & e) { return e.status; } catch (UsageError & e) { diff --git a/src/libutil/signals.cc b/src/libutil/signals.cc index f5c79b325..41fdc9dc8 100644 --- a/src/libutil/signals.cc +++ b/src/libutil/signals.cc @@ -9,21 +9,14 @@ namespace nix { std::atomic _isInterrupted = false; -static thread_local bool interruptThrown = false; thread_local std::function interruptCheck; -void setInterruptThrown() -{ - interruptThrown = true; -} - void _interrupted() { /* Block user interrupts while an exception is being handled. Throwing an exception while another exception is being handled kills the program! */ - if (!interruptThrown && !std::uncaught_exceptions()) { - interruptThrown = true; + if (!std::uncaught_exceptions()) { throw Interrupted("interrupted by the user"); } } diff --git a/src/libutil/signals.hh b/src/libutil/signals.hh index c58dc37cf..71593df95 100644 --- a/src/libutil/signals.hh +++ b/src/libutil/signals.hh @@ -22,8 +22,6 @@ extern std::atomic _isInterrupted; extern thread_local std::function interruptCheck; -void setInterruptThrown(); - void _interrupted(); void inline checkInterrupt()