#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/Api.hpp" #include #include #include #include #include #include #include using Handler = void (APS5_VABI *)(int); namespace { using SignalSet = std::array; volatile std::sig_atomic_t received = 0; void Require(bool value, const char* message) { if (!value) { std::fprintf(stderr, "legacy signal mask: %s\n", message); std::abort(); } } SignalSet CurrentMask() { SignalSet mask{}; Require(sigprocmask_nid_postfix(1, nullptr, mask.data()) == 0, "cannot read the current mask"); return mask; } void APS5_VABI Receive(int number) { received = number; } } int main() { const SignalSet original = CurrentMask(); SignalSet expected{0x20, 0x81234567, 0x89abcdef, 0xfedcba98}; Require(sigprocmask_nid_postfix(3, expected.data(), nullptr) == 0, "cannot seed the mask"); *__error_nid_postfix() = 123; Require(sigblock_nid_postfix(0) == 0x20 && CurrentMask() == expected, "an empty block changed the mask"); Require(sigblock_nid_postfix(std::numeric_limits::min()) == 0x20, "blocking lost the previous mask"); expected[0] |= 0x80000000; Require(CurrentMask() == expected, "blocking did not preserve the existing mask"); Require(sigblock_nid_postfix(-1) == std::bit_cast(expected[0]), "the previous mask was not signed at bit 31"); constexpr std::uint32_t unblockable = (1u << 8) | (1u << 16); expected[0] = ~unblockable; Require(CurrentMask() == expected, "blocking all signals lost upper words or blocked SIGKILL/SIGSTOP"); constexpr std::uint32_t userSignal = 1u << 29; Require(sigsetmask_nid_postfix(userSignal) == std::bit_cast(expected[0]), "replacement lost the previous mask"); expected = {userSignal, 0, 0, 0}; Require(CurrentMask() == expected, "replacement did not clear the upper mask words"); Require(sigsetmask_nid_postfix(-1) == static_cast(userSignal), "a negative replacement lost the previous mask"); Require(CurrentMask() == SignalSet{~unblockable, 0, 0, 0}, "a negative replacement was sign-extended or kept unmaskable signals"); Require(sigsetmask_nid_postfix(0) == std::bit_cast(~unblockable), "clearing lost the previous mask"); Require(CurrentMask() == SignalSet{}, "the signal mask was not cleared"); Require(*__error_nid_postfix() == 123, "mask operations changed errno"); const Handler previous = signal_nid_postfix(30, Receive); Require(previous != reinterpret_cast(std::numeric_limits::max()), "cannot install the signal handler"); Require(sigblock_nid_postfix(userSignal) == 0, "cannot block SIGUSR1"); Require(raise_nid_postfix(30) == 0 && received == 0, "a blocked signal was delivered"); GuestSignalSet pending{}; Require(sigpending_nid_postfix(&pending) == 0 && (pending.bits[0] & userSignal) != 0, "a blocked signal was not queued"); Require(sigsetmask_nid_postfix(0) == static_cast(userSignal) && received == 30, "clearing the mask did not deliver SIGUSR1"); Require(sigpending_nid_postfix(&pending) == 0 && (pending.bits[0] & userSignal) == 0, "the delivered signal remained pending"); Require(signal_nid_postfix(30, previous) == Receive, "cannot restore the signal handler"); Require(sigprocmask_nid_postfix(3, original.data(), nullptr) == 0, "cannot restore the original mask"); }