diff --git a/Userland/Shell/AST.cpp b/Userland/Shell/AST.cpp index f45c547ca3..b945fd9cb8 100644 --- a/Userland/Shell/AST.cpp +++ b/Userland/Shell/AST.cpp @@ -1190,7 +1190,7 @@ RefPtr ForLoop::run(RefPtr shell) return IterationDecision::Continue; } - if (!shell->has_error(Shell::ShellError::None)) + if (shell->has_any_error() && !shell->has_error(Shell::ShellError::InternalControlFlowInterrupted)) return IterationDecision::Break; if (block_value->is_job()) { @@ -1199,13 +1199,12 @@ RefPtr ForLoop::run(RefPtr shell) return IterationDecision::Continue; shell->block_on_job(job); - if (job->signaled()) { - if (job->termination_signal() == SIGINT) + if (shell->has_any_error()) { + if (shell->has_error(Shell::ShellError::InternalControlFlowInterrupted)) ++consecutive_interruptions; - else + + if (shell->has_error(Shell::ShellError::InternalControlFlowKilled)) return IterationDecision::Break; - } else { - consecutive_interruptions = 0; } } return IterationDecision::Continue; @@ -1216,11 +1215,16 @@ RefPtr ForLoop::run(RefPtr shell) Optional index_name = m_index_variable.has_value() ? Optional(m_index_variable->name) : Optional(); size_t i = 0; m_iterated_expression->for_each_entry(shell, [&](auto value) { - if (consecutive_interruptions == 2) + if (consecutive_interruptions >= 2) return IterationDecision::Break; - if (shell && shell->has_any_error()) - return IterationDecision::Break; + if (shell) { + if (shell->has_error(Shell::ShellError::InternalControlFlowInterrupted)) + shell->take_error(); + + if (shell->has_any_error()) + return IterationDecision::Break; + } RefPtr block_value; @@ -1240,11 +1244,16 @@ RefPtr ForLoop::run(RefPtr shell) }); } else { for (;;) { - if (shell && shell->has_any_error()) + if (consecutive_interruptions >= 2) break; - if (consecutive_interruptions == 2) - break; + if (shell) { + if (shell->has_error(Shell::ShellError::InternalControlFlowInterrupted)) + shell->take_error(); + + if (shell->has_any_error()) + break; + } RefPtr block_value = m_block->run(shell); if (run(block_value) == IterationDecision::Break) diff --git a/Userland/Shell/Shell.cpp b/Userland/Shell/Shell.cpp index 9b9928c2f6..4b129aae76 100644 --- a/Userland/Shell/Shell.cpp +++ b/Userland/Shell/Shell.cpp @@ -1765,7 +1765,12 @@ void Shell::notify_child_event() } if (child_pid == job.pid()) { if (WIFSIGNALED(wstatus) && !WIFSTOPPED(wstatus)) { - job.set_signalled(WTERMSIG(wstatus)); + auto signal = WTERMSIG(wstatus); + job.set_signalled(signal); + if (signal == SIGINT) + raise_error(ShellError::InternalControlFlowInterrupted, "Interrupted"sv, job.command().position); + else if (signal == SIGKILL) + raise_error(ShellError::InternalControlFlowKilled, "Interrupted"sv, job.command().position); } else if (WIFEXITED(wstatus)) { job.set_has_exit(WEXITSTATUS(wstatus)); } else if (WIFSTOPPED(wstatus)) { @@ -1998,6 +2003,8 @@ void Shell::possibly_print_error() const break; case ShellError::InternalControlFlowBreak: case ShellError::InternalControlFlowContinue: + case ShellError::InternalControlFlowInterrupted: + case ShellError::InternalControlFlowKilled: return; case ShellError::None: return; diff --git a/Userland/Shell/Shell.h b/Userland/Shell/Shell.h index 5938f490bb..e12882e6d9 100644 --- a/Userland/Shell/Shell.h +++ b/Userland/Shell/Shell.h @@ -228,6 +228,8 @@ public: None, InternalControlFlowBreak, InternalControlFlowContinue, + InternalControlFlowInterrupted, + InternalControlFlowKilled, EvaluatedSyntaxError, NonExhaustiveMatchRules, InvalidGlobError, @@ -260,6 +262,8 @@ public: switch (error) { case ShellError::InternalControlFlowBreak: case ShellError::InternalControlFlowContinue: + case ShellError::InternalControlFlowInterrupted: + case ShellError::InternalControlFlowKilled: return true; default: return false;