summaryrefslogtreecommitdiff
path: root/Userland/Shell/Shell.cpp
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2022-01-09 09:19:01 +0330
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2022-01-09 11:16:17 +0330
commitea667506405213d9e09116c8c30381c0fdcfe47b (patch)
treeebaf4e670c96970fea676902117083b0f0f91525 /Userland/Shell/Shell.cpp
parentabaee3a3250e39b24b8e2338a04eb3245862d9a1 (diff)
downloadserenity-ea667506405213d9e09116c8c30381c0fdcfe47b.zip
Shell: Make interrupts kill the whole chain and not just the current job
This makes interrupting `sleep 10; echo hi` not print `hi` anymore, which is the expected behaviour anyway. Also fixes the problem with fast-running loops "eating" interrupts and not quitting.
Diffstat (limited to 'Userland/Shell/Shell.cpp')
-rw-r--r--Userland/Shell/Shell.cpp9
1 files changed, 8 insertions, 1 deletions
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;