diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 5c78d2a5d8..18bf12e062 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -322,11 +322,9 @@ bool Scheduler::pick_next() if (&thread == current) return IterationDecision::Continue; // We know how to interrupt blocked processes, but if they are just executing - // at some random point in the kernel, let them continue. They'll be in userspace - // sooner or later and we can deliver the signal then. - // FIXME: Maybe we could check when returning from a syscall if there's a pending - // signal and dispatch it then and there? Would that be doable without the - // syscall effectively being "interrupted" despite having completed? + // at some random point in the kernel, let them continue. + // Before returning to userspace from a syscall, we will block a thread if it has any + // pending unmasked signals, allowing it to be dispatched then. if (thread.in_kernel() && !thread.is_blocked() && !thread.is_stopped()) return IterationDecision::Continue; // NOTE: dispatch_one_pending_signal() may unblock the process. 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::Reason::Signal); }