diff --git a/Kernel/Syscalls/sigaction.cpp b/Kernel/Syscalls/sigaction.cpp index c5a94d27c13..2226e816bd0 100644 --- a/Kernel/Syscalls/sigaction.cpp +++ b/Kernel/Syscalls/sigaction.cpp @@ -104,6 +104,7 @@ ErrorOr Process::sys$sigreturn([[maybe_unused]] RegisterState& register auto saved_ax = TRY(copy_typed_from_user(stack_ptr)); Thread::current()->m_signal_mask = ucontext.uc_sigmask; + Thread::current()->m_currently_handled_signal = 0; #if ARCH(X86_64) auto sp = registers.rsp; #elif ARCH(I386) diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 5c1306b4777..2d84d761af9 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -1052,6 +1052,8 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal) ScopedAddressSpaceSwitcher switcher(m_process); + m_currently_handled_signal = signal; + u32 old_signal_mask = m_signal_mask; u32 new_signal_mask = m_signal_action_masks[signal].value_or(action.mask); if ((action.flags & SA_NODEFER) == SA_NODEFER) diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 42de69c8ab6..b94bb226615 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -1210,6 +1210,7 @@ private: u32 m_ticks_in_user { 0 }; u32 m_ticks_in_kernel { 0 }; u32 m_pending_signals { 0 }; + u8 m_currently_handled_signal { 0 }; u32 m_signal_mask { 0 }; FlatPtr m_alternative_signal_stack { 0 }; FlatPtr m_alternative_signal_stack_size { 0 }; diff --git a/Kernel/ThreadBlockers.cpp b/Kernel/ThreadBlockers.cpp index e05a94fed1d..5ef39243152 100644 --- a/Kernel/ThreadBlockers.cpp +++ b/Kernel/ThreadBlockers.cpp @@ -474,7 +474,15 @@ bool Thread::SignalBlocker::check_pending_signals(bool from_add_blocker) if (m_did_unblock) return false; - auto matching_pending_signal = bit_scan_forward(thread().pending_signals() & m_pending_set); + auto pending_signals = thread().pending_signals() & m_pending_set; + + // Also unblock if we have just "handled" that signal and are in the procecss + // of running their signal handler (i.e. we just unmarked the signal as pending). + if (thread().m_currently_handled_signal) + pending_signals |= (1 << (thread().m_currently_handled_signal - 1)) & m_pending_set; + + auto matching_pending_signal = bit_scan_forward(pending_signals); + if (matching_pending_signal == 0) return false;