summaryrefslogtreecommitdiff
path: root/Kernel/Syscall.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2020-01-12 15:04:33 +0100
committerAndreas Kling <awesomekling@gmail.com>2020-01-12 15:04:33 +0100
commit8b54ba0d616acc8f26badc8f09589042b2d91552 (patch)
tree59a0109cb3ecc82b40253b8ce907833afc464083 /Kernel/Syscall.cpp
parent62a191b59a8c77fc6a5d8a7255157fc273305909 (diff)
downloadserenity-8b54ba0d616acc8f26badc8f09589042b2d91552.zip
Kernel: Dispatch pending signals when returning from a syscall
It was quite easy to put the system into a heavy churn state by doing e.g "cat /dev/zero". It was then basically impossible to kill the "cat" process, even with "kill -9", since signals are only delivered in two conditions: a) The target thread is blocked in the kernel b) The target thread is running in userspace However, since "cat /dev/zero" command spends most of its time actively running in the kernel, not blocked, the signal dispatch code just kept postponing actually handling the signal indefinitely. To fix this, we now check before returning from a syscall if there are any pending unmasked signals, and if so, we take a dramatic pause by blocking the current thread, knowing it will immediately be unblocked by signal dispatch anyway. :^)
Diffstat (limited to 'Kernel/Syscall.cpp')
-rw-r--r--Kernel/Syscall.cpp3
1 files changed, 3 insertions, 0 deletions
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index e4e39d6769..0a9cd38f3c 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -135,4 +135,7 @@ void syscall_handler(RegisterDump regs)
// Check if we're supposed to return to userspace or just die.
current->die_if_needed();
+
+ if (current->has_unmasked_pending_signals())
+ (void)current->block<Thread::SemiPermanentBlocker>(Thread::SemiPermanentBlocker::Reason::Signal);
}