diff --git a/Shell/AST.cpp b/Shell/AST.cpp index d337581631..64a9ef86ca 100644 --- a/Shell/AST.cpp +++ b/Shell/AST.cpp @@ -30,6 +30,7 @@ #include #include #include +#include //#define EXECUTE_DEBUG @@ -754,6 +755,8 @@ RefPtr ForLoop::run(RefPtr shell) if (!m_block) return create({}); + size_t consecutive_interruptions = 0; + NonnullRefPtrVector values; auto resolved = m_iterated_expression->run(shell)->resolve_without_cast(shell); if (resolved->is_list_without_resolution()) @@ -762,6 +765,9 @@ RefPtr ForLoop::run(RefPtr shell) values = create(resolved->resolve_as_list(shell))->values(); for (auto& value : values) { + if (consecutive_interruptions == 2) + break; + auto frame = shell->push_frame(); shell->set_local_variable(m_variable_name, value); @@ -771,6 +777,13 @@ RefPtr ForLoop::run(RefPtr shell) if (!job || job->is_running_in_background()) continue; shell->block_on_job(job); + if (job->signaled() + && (job->termination_signal() == SIGINT + || job->termination_signal() == SIGKILL + || job->termination_signal() == SIGQUIT)) + ++consecutive_interruptions; + else + consecutive_interruptions = 0; } } diff --git a/Shell/Job.h b/Shell/Job.h index 75636a8758..9de08bfebc 100644 --- a/Shell/Job.h +++ b/Shell/Job.h @@ -59,7 +59,17 @@ public: const String& cmd() const { return m_cmd; } u64 job_id() const { return m_job_id; } bool exited() const { return m_exited; } - int exit_code() const { return m_exit_code; } + bool signaled() const { return m_term_sig != -1; } + int exit_code() const + { + ASSERT(exited()); + return m_exit_code; + } + int termination_signal() const + { + ASSERT(signaled()); + return m_term_sig; + } bool should_be_disowned() const { return m_should_be_disowned; } void disown() { m_should_be_disowned = true; } bool is_running_in_background() const { return m_running_in_background; } @@ -82,6 +92,16 @@ public: if (on_exit) on_exit(*this); } + void set_signalled(int sig) + { + if (m_exited) + return; + m_exited = true; + m_exit_code = 126; + m_term_sig = sig; + if (on_exit) + on_exit(*this); + } void set_is_suspended(bool value) const { m_is_suspended = value; } @@ -118,6 +138,7 @@ private: bool m_exited { false }; bool m_running_in_background { false }; int m_exit_code { -1 }; + int m_term_sig { -1 }; Core::ElapsedTimer m_command_timer; mutable bool m_active { true }; mutable bool m_is_suspended { false }; diff --git a/Shell/main.cpp b/Shell/main.cpp index 6c279ba488..80ef3aa22d 100644 --- a/Shell/main.cpp +++ b/Shell/main.cpp @@ -105,10 +105,10 @@ int main(int argc, char** argv) } #endif if (child_pid == job.pid()) { - if (WIFEXITED(wstatus)) { + if (WIFSIGNALED(wstatus) && !WIFSTOPPED(wstatus)) { + job.set_signalled(WTERMSIG(wstatus)); + } else if (WIFEXITED(wstatus)) { job.set_has_exit(WEXITSTATUS(wstatus)); - } else if (WIFSIGNALED(wstatus) && !WIFSTOPPED(wstatus)) { - job.set_has_exit(126); } else if (WIFSTOPPED(wstatus)) { job.unblock(); job.set_is_suspended(true);