diff --git a/External/FEXCore/Source/Interface/Core/SignalDelegator.cpp b/External/FEXCore/Source/Interface/Core/SignalDelegator.cpp index 46a4232ab..e49f93c7a 100644 --- a/External/FEXCore/Source/Interface/Core/SignalDelegator.cpp +++ b/External/FEXCore/Source/Interface/Core/SignalDelegator.cpp @@ -21,6 +21,7 @@ namespace FEXCore { // Guest signal sa_mask is per thread! SignalDelegator::GuestSAMask Guest_sa_mask[SignalDelegator::MAX_SIGNALS]{}; uint32_t CurrentSignal{}; + uint64_t GuestProcMask{}; }; thread_local ThreadState ThreadData{}; @@ -94,11 +95,18 @@ namespace FEXCore { } } + // Signal specific mask check if (SigIsMember(&ThreadData.Guest_sa_mask[ThreadData.CurrentSignal], Signal)) { // If we are in a signal and our signal mask is blocking this signal then ignore it return; } + // Thread specific mask check + if (ThreadData.GuestProcMask & (Signal - 1)) { + // If the thread specific mask masks the signal then it is hidden from the guest + return; + } + ThreadData.CurrentSignal = Signal; // We have an emulation thread pointer, we can now modify its state @@ -396,4 +404,27 @@ namespace FEXCore { return 0; } + uint64_t SignalDelegator::GuestSigProcMask(int how, const uint64_t *set, uint64_t *oldset) { + if (!!oldset) { + *oldset = ThreadData.GuestProcMask; + } + + if (!!set) { + uint64_t IgnoredSignalsMask = ~((1ULL << (SIGKILL - 1)) | (1ULL << (SIGSTOP - 1))); + if (how == SIG_BLOCK) { + ThreadData.GuestProcMask |= *set & IgnoredSignalsMask; + } + else if (how == SIG_UNBLOCK) { + ThreadData.GuestProcMask &= *set & IgnoredSignalsMask; + } + else if (how == SIG_SETMASK) { + ThreadData.GuestProcMask = *set & IgnoredSignalsMask; + } + else { + return -EINVAL; + } + } + + return 0; + } } diff --git a/External/FEXCore/Source/Interface/Core/SignalDelegator.h b/External/FEXCore/Source/Interface/Core/SignalDelegator.h index e5609aec4..d6f7cb2cb 100644 --- a/External/FEXCore/Source/Interface/Core/SignalDelegator.h +++ b/External/FEXCore/Source/Interface/Core/SignalDelegator.h @@ -82,6 +82,8 @@ namespace Core { uint64_t RegisterGuestSigAltStack(const stack_t *ss, stack_t *old_ss); + uint64_t GuestSigProcMask(int how, const uint64_t *set, uint64_t *oldset); + // Called from the thunk handler to handle the signal void HandleSignal(int Signal, void *Info, void *UContext); diff --git a/External/FEXCore/Source/Interface/HLE/Syscalls/Signals.cpp b/External/FEXCore/Source/Interface/HLE/Syscalls/Signals.cpp index b387cd413..e62c36b2d 100644 --- a/External/FEXCore/Source/Interface/HLE/Syscalls/Signals.cpp +++ b/External/FEXCore/Source/Interface/HLE/Syscalls/Signals.cpp @@ -14,10 +14,8 @@ namespace FEXCore::HLE { return Thread->CTX->SignalDelegation.RegisterGuestSignalHandler(signum, act, oldact); }); - REGISTER_SYSCALL_IMPL(rt_sigprocmask, [](FEXCore::Core::InternalThreadState *Thread, int how, const sigset_t *set, sigset_t *oldset) -> uint64_t { - // XXX: Pass through SignalDelegator - uint64_t Result = ::sigprocmask(how, set, oldset); - SYSCALL_ERRNO(); + REGISTER_SYSCALL_IMPL(rt_sigprocmask, [](FEXCore::Core::InternalThreadState *Thread, int how, const uint64_t *set, uint64_t *oldset) -> uint64_t { + return Thread->CTX->SignalDelegation.GuestSigProcMask(how, set, oldset); }); REGISTER_SYSCALL_IMPL(sigaltstack, [](FEXCore::Core::InternalThreadState *Thread, const stack_t *ss, stack_t *old_ss) -> uint64_t {