mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
The blocked mask of sigprocmask, _sigprocmask, pthread_sigmask and sigsuspend was one process-wide set, so a thread changing its mask changed every thread's, and scePthreadCreate did not hand the creating thread's mask to the new thread. Each guest thread now has its own blocked mask and handler holds, and a new thread starts with its creator's mask. The pending set stays the process-wide one, so a signal that raise leaves pending is still taken by sigwait and sigtimedwait on any thread and delivered by the first thread that unblocks it. A SIGALRM expiry checks the mask of the thread that armed the timer. Fixes #2879. Claude-Session: https://claude.ai/code/session_012SLQbhAiexxW6TtjYToW8a
580 lines
32 KiB
C++
580 lines
32 KiB
C++
#include "prx/libkernel/include/Api.hpp"
|
|
#include "prx/libc/include/Api.hpp"
|
|
#include "prx/libSceLibcInternal/include/Api.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <csignal>
|
|
#include <initializer_list>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <stdexcept>
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <thread>
|
|
using Handler = void (APS5_VABI *)(int);
|
|
|
|
extern "C" {
|
|
|
|
unsigned int APS5_VABI GuestAlarm_nid_no_patch(unsigned int);
|
|
|
|
}
|
|
|
|
static_assert(sizeof(GuestSigaction) == 32);
|
|
extern GuestSignalSet _sigintr_nid_postfix;
|
|
static bool Same(const GuestSigaction& left, const GuestSigaction& right) {
|
|
return left.handler == right.handler && left.flags == right.flags && std::memcmp(&left.mask, &right.mask, sizeof(left.mask)) == 0;
|
|
}
|
|
volatile std::sig_atomic_t received = 0;
|
|
volatile std::uintptr_t handlerReturn = 0;
|
|
void APS5_VABI InfoCallback(int, void*, void*) {}
|
|
struct SuspendWait {
|
|
const GuestSignalSet* mask = nullptr;
|
|
int result = 0;
|
|
int error = 0;
|
|
};
|
|
void* APS5_VABI SuspendEntry(void* arg) {
|
|
auto& wait = *static_cast<SuspendWait*>(arg);
|
|
wait.result = sigsuspend_nid_postfix(wait.mask);
|
|
wait.error = *__error_nid_postfix();
|
|
return nullptr;
|
|
}
|
|
struct SuspendSender {
|
|
Pthread target = nullptr;
|
|
int result = -1;
|
|
};
|
|
struct EndingThread {
|
|
std::atomic<bool> release{false};
|
|
};
|
|
void* APS5_VABI EndingEntry(void* arg) {
|
|
auto& state = *static_cast<EndingThread*>(arg);
|
|
while (!state.release.load()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
return nullptr;
|
|
}
|
|
struct MaskProbe {
|
|
GuestSignalSet inherited{};
|
|
GuestSignalSet changed{};
|
|
GuestSignalSet afterUnblock{};
|
|
int waited = 0;
|
|
};
|
|
void* APS5_VABI ChildChangesMask(void* arg) {
|
|
auto& probe = *static_cast<MaskProbe*>(arg);
|
|
const GuestSignalSet hangup{{0x2, 0, 0, 0}};
|
|
sigprocmask_nid_postfix(1, nullptr, &probe.inherited);
|
|
sigprocmask_nid_postfix(3, &hangup, nullptr);
|
|
sigprocmask_nid_postfix(1, nullptr, &probe.changed);
|
|
return nullptr;
|
|
}
|
|
void* APS5_VABI ChildTakesPending(void* arg) {
|
|
auto& probe = *static_cast<MaskProbe*>(arg);
|
|
const GuestSignalSet user2{{1u << 30, 0, 0, 0}};
|
|
const KernelTimespec none{0, 0};
|
|
probe.waited = sigtimedwait_nid_postfix(&user2, nullptr, &none);
|
|
return nullptr;
|
|
}
|
|
void* APS5_VABI ChildUnblocks(void* arg) {
|
|
auto& probe = *static_cast<MaskProbe*>(arg);
|
|
const GuestSignalSet user2{{1u << 30, 0, 0, 0}};
|
|
sigprocmask_nid_postfix(2, &user2, nullptr);
|
|
sigprocmask_nid_postfix(1, nullptr, &probe.afterUnblock);
|
|
return nullptr;
|
|
}
|
|
void* APS5_VABI SuspendSend(void* arg) {
|
|
auto& sender = *static_cast<SuspendSender*>(arg);
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
sender.result = pthread_kill_nid_postfix(sender.target, 30);
|
|
return nullptr;
|
|
}
|
|
void APS5_VABI Callback(int value) {
|
|
received = value;
|
|
handlerReturn = reinterpret_cast<std::uintptr_t>(__builtin_return_address(0));
|
|
}
|
|
GuestSignalSet maskInHandler{};
|
|
void APS5_VABI MaskCallback(int value) {
|
|
received = value;
|
|
sigprocmask_nid_postfix(1, nullptr, &maskInHandler);
|
|
|
|
}
|
|
static void Require(bool value) { if (!value) std::abort(); }
|
|
static void CheckSignalPointerFaults() {
|
|
constexpr std::size_t page = 0x4000;
|
|
void* memory = nullptr;
|
|
Require(sceKernelMapFlexibleMemory(&memory, page, 3, 0) == 0 && memory != nullptr);
|
|
Require(sceKernelMprotect(memory, page, 1) == 0);
|
|
const auto readOnly = memory;
|
|
const auto unreadable = reinterpret_cast<void*>(std::uintptr_t{0x10});
|
|
const auto fails = [](int result) { return result == -1 && *__error_nid_postfix() == 14; };
|
|
constexpr int user = 30;
|
|
GuestSigaction previous{};
|
|
Require(fails(sigaction_nid_postfix(user, static_cast<const GuestSigaction*>(unreadable), nullptr)));
|
|
Require(fails(sigaction_nid_postfix(0, static_cast<const GuestSigaction*>(unreadable), nullptr)));
|
|
Require(fails(sigaction_nid_postfix(user, nullptr, static_cast<GuestSigaction*>(unreadable))));
|
|
Require(fails(sigaction_nid_postfix(user, nullptr, static_cast<GuestSigaction*>(readOnly))));
|
|
Require(sigaction_nid_postfix(0, nullptr, &previous) == -1 && *__error_nid_postfix() == 22);
|
|
Require(sigaction_nid_postfix(user, nullptr, &previous) == 0);
|
|
GuestSignalSet blocked{}, set{{1u << (user - 1), 0, 0, 0}}, none{};
|
|
Require(sigprocmask_nid_postfix(3, nullptr, &blocked) == 0);
|
|
Require(fails(sigprocmask_nid_postfix(1, unreadable, nullptr)));
|
|
Require(fails(sigprocmask_nid_postfix(9, unreadable, nullptr)));
|
|
Require(sigprocmask_nid_postfix(9, &set, nullptr) == -1 && *__error_nid_postfix() == 22);
|
|
Require(fails(sigprocmask_nid_postfix(1, nullptr, unreadable)));
|
|
Require(fails(sigprocmask_nid_postfix(1, nullptr, readOnly)));
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &none) == 0 && std::memcmp(&none, &blocked, sizeof(none)) == 0);
|
|
Require(fails(sigprocmask_nid_postfix(1, &set, readOnly)));
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &none) == 0 && (none.bits[0] & set.bits[0]) != 0);
|
|
Require(sigprocmask_nid_postfix(3, &blocked, nullptr) == 0);
|
|
Require(pthread_sigmask_nid_postfix(1, static_cast<const GuestSignalSet*>(unreadable), nullptr) == 14);
|
|
Require(pthread_sigmask_nid_postfix(1, nullptr, static_cast<GuestSignalSet*>(readOnly)) == 14);
|
|
Require(pthread_sigmask_nid_postfix(9, static_cast<const GuestSignalSet*>(unreadable), nullptr) == 14);
|
|
Require(pthread_sigmask_nid_postfix(9, &set, nullptr) == 22);
|
|
Require(sigprocmask_nid_postfix(3, &blocked, nullptr) == 0);
|
|
Require(fails(sigaltstack_nid_postfix(static_cast<const GuestStack*>(unreadable), nullptr)));
|
|
Require(fails(sigaltstack_nid_postfix(nullptr, static_cast<GuestStack*>(unreadable))));
|
|
Require(fails(sigaltstack_nid_postfix(nullptr, static_cast<GuestStack*>(readOnly))));
|
|
Require(fails(sigpending_nid_postfix(static_cast<GuestSignalSet*>(unreadable))));
|
|
Require(fails(sigpending_nid_postfix(static_cast<GuestSignalSet*>(readOnly))));
|
|
Require(fails(sigpending_nid_postfix(nullptr)));
|
|
}
|
|
|
|
int main() {
|
|
const auto invalid = reinterpret_cast<Handler>(static_cast<std::uintptr_t>(-1));
|
|
CheckSignalPointerFaults();
|
|
const auto ignore = reinterpret_cast<Handler>(std::uintptr_t{1});
|
|
Require(signal_nid_postfix(9, Callback) == invalid);
|
|
Require(*__error_nid_postfix() == 22);
|
|
Require(signal_nid_postfix(15, Callback) != invalid);
|
|
Require(raise_nid_postfix(15) == 0 && received == 15);
|
|
Require(handlerReturn != 0 && _is_signal_return_nid_postfix(handlerReturn) == 0);
|
|
Require(_is_signal_return_nid_postfix(reinterpret_cast<std::uintptr_t>(Callback)) == 0);
|
|
Require(_is_signal_return_nid_postfix(0) == 0);
|
|
received = 0;
|
|
Require(raise_nid_postfix(15) == 0 && received == 15);
|
|
received = 0;
|
|
Require(pthread_kill_nid_postfix(scePthreadSelf(), 15) == 0 && received == 15);
|
|
received = 0;
|
|
Require(pthread_kill_nid_postfix(scePthreadSelf(), 0) == 0 && received == 0);
|
|
Require(pthread_kill_nid_postfix(scePthreadSelf(), 200) == 22);
|
|
Require(pthread_kill_nid_postfix(scePthreadSelf(), -1) == 22);
|
|
Require(pthread_kill_nid_postfix(nullptr, 15) == 3);
|
|
Require(pthread_kill_nid_postfix(nullptr, 128) == 3);
|
|
Require(pthread_kill_nid_postfix(nullptr, 129) == 22);
|
|
Require(pthread_kill_nid_postfix(reinterpret_cast<Pthread>(std::uintptr_t{0x10}), 15) == 3);
|
|
Require(pthread_kill_nid_postfix(reinterpret_cast<Pthread>(std::uintptr_t{0x10}), 0) == 3);
|
|
{
|
|
EndingThread ending;
|
|
Pthread thread = nullptr;
|
|
Require(scePthreadCreate(&thread, nullptr, EndingEntry, &ending, nullptr) == 0);
|
|
Require(pthread_kill_nid_postfix(thread, 0) == 0);
|
|
ending.release.store(true);
|
|
int answer = 0;
|
|
for (int attempt = 0; attempt < 2000 && (answer = pthread_kill_nid_postfix(thread, 0)) != 3; ++attempt)
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
Require(answer == 3);
|
|
Require(pthread_kill_nid_postfix(thread, 15) == 3);
|
|
Require(scePthreadJoin(thread, nullptr) == 0);
|
|
Require(pthread_kill_nid_postfix(thread, 0) == 3);
|
|
}
|
|
Require(received == 0);
|
|
Require(signal_nid_postfix(15, ignore) != invalid);
|
|
received = 0;
|
|
Require(raise_nid_postfix(15) == 0 && received == 0);
|
|
Require(signal_nid_postfix(15, nullptr) == ignore);
|
|
Require(raise_nid_postfix(100) == -1 && *__error_nid_postfix() == 22);
|
|
*__error_nid_postfix() = 0;
|
|
received = 0;
|
|
Require(raise_nid_postfix(0) == 0 && received == 0 && *__error_nid_postfix() == 0);
|
|
Require(raise_nid_postfix(129) == -1 && *__error_nid_postfix() == 22);
|
|
Require(raise_nid_postfix(-1) == -1 && *__error_nid_postfix() == 22);
|
|
GuestSignalSet blocked{{0x20, 0, 0, 0}};
|
|
GuestSignalSet previous{{}};
|
|
Require(sigprocmask_nid_postfix(3, &blocked, &previous) == 0);
|
|
Require(previous.bits[0] == 0);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0);
|
|
Require(previous.bits[0] == 0x20);
|
|
Require(sigprocmask_nid_postfix(2, &blocked, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0);
|
|
Require(previous.bits[0] == 0);
|
|
*__error_nid_postfix() = 0;
|
|
Require(pthread_sigmask_nid_postfix(1, &blocked, nullptr) == 0);
|
|
Require(pthread_sigmask_nid_postfix(0, &blocked, &previous) == 22);
|
|
Require(pthread_sigmask_nid_postfix(4, &blocked, &previous) == 22);
|
|
Require(*__error_nid_postfix() == 0);
|
|
Require(pthread_sigmask_nid_postfix(0, nullptr, &previous) == 0);
|
|
Require(previous.bits[0] == 0x20);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == 0x20);
|
|
Require(pthread_sigmask_nid_postfix(2, &blocked, &previous) == 0 && previous.bits[0] == 0x20);
|
|
Require(pthread_sigmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == 0);
|
|
const GuestSignalSet withKillAndStop{{(1u << 8) | (1u << 16) | 0x20, 0, 0, 0}};
|
|
const GuestSignalSet noSignals{{0, 0, 0, 0}};
|
|
Require(sigprocmask_nid_postfix(1, &withKillAndStop, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == 0x20);
|
|
Require(sigprocmask_nid_postfix(3, &noSignals, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(3, &withKillAndStop, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == 0x20);
|
|
Require(sigprocmask_nid_postfix(3, &noSignals, nullptr) == 0);
|
|
Require(pthread_sigmask_nid_postfix(1, &withKillAndStop, nullptr) == 0);
|
|
Require(pthread_sigmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == 0x20);
|
|
Require(pthread_sigmask_nid_postfix(3, &noSignals, nullptr) == 0);
|
|
{
|
|
const GuestSignalSet parentMask{{1u << 13, 0, 0, 0}};
|
|
Require(sigprocmask_nid_postfix(3, &parentMask, nullptr) == 0);
|
|
MaskProbe probe;
|
|
Pthread child = nullptr;
|
|
Require(scePthreadCreate(&child, nullptr, ChildChangesMask, &probe, nullptr) == 0);
|
|
Require(scePthreadJoin(child, nullptr) == 0);
|
|
Require(probe.inherited.bits[0] == 1u << 13 && probe.changed.bits[0] == 0x2);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == 1u << 13);
|
|
Require(sigprocmask_nid_postfix(3, &noSignals, nullptr) == 0);
|
|
}
|
|
{
|
|
const GuestSignalSet user2{{1u << 30, 0, 0, 0}};
|
|
const auto old = signal_nid_postfix(31, Callback);
|
|
Require(old != invalid);
|
|
Require(sigprocmask_nid_postfix(1, &user2, nullptr) == 0);
|
|
received = 0;
|
|
Require(raise_nid_postfix(31) == 0 && received == 0);
|
|
MaskProbe probe;
|
|
Pthread child = nullptr;
|
|
Require(scePthreadCreate(&child, nullptr, ChildTakesPending, &probe, nullptr) == 0);
|
|
Require(scePthreadJoin(child, nullptr) == 0);
|
|
Require(probe.waited == 31 && received == 0);
|
|
Require(sigpending_nid_postfix(&previous) == 0 && previous.bits[0] == 0);
|
|
Require(raise_nid_postfix(31) == 0 && received == 0);
|
|
Require(scePthreadCreate(&child, nullptr, ChildUnblocks, &probe, nullptr) == 0);
|
|
Require(scePthreadJoin(child, nullptr) == 0);
|
|
Require(received == 31 && probe.afterUnblock.bits[0] == 0);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == 1u << 30);
|
|
Require(sigprocmask_nid_postfix(3, &noSignals, nullptr) == 0);
|
|
Require(signal_nid_postfix(31, old) != invalid);
|
|
received = 0;
|
|
}
|
|
|
|
const auto callback = reinterpret_cast<std::uintptr_t>(Callback);
|
|
const auto infoCallback = reinterpret_cast<std::uintptr_t>(InfoCallback);
|
|
GuestSigaction current{};
|
|
std::memset(¤t, 0xa5, sizeof(current));
|
|
Require(sigaction_nid_postfix(15, nullptr, ¤t) == 0);
|
|
Require(current.handler == 0 && current.flags == 0x2 && current.mask.bits[0] == 0 && current.mask.bits[3] == 0);
|
|
const GuestSigaction term{callback, 0, {{0x4000, 0, 0, 0x80000000u}}};
|
|
Require(sigaction_nid_postfix(15, &term, ¤t) == 0 && current.handler == 0);
|
|
received = 0;
|
|
Require(raise_nid_postfix(15) == 0 && received == 15);
|
|
Require(sigaction_nid_postfix(15, nullptr, ¤t) == 0);
|
|
Require(Same(current, term));
|
|
const GuestSigaction defaults{0, 0, {}};
|
|
Require(sigaction_nid_postfix(15, &defaults, nullptr) == 0);
|
|
Require(signal_nid_postfix(15, Callback) == nullptr);
|
|
Require(sigaction_nid_postfix(15, nullptr, ¤t) == 0 && current.handler == callback && current.flags == 0x2);
|
|
Require(signal_nid_postfix(15, nullptr) == Callback);
|
|
for (const int flags : {0x80, 0x100, 0x8000, 0x40 | 0x80}) {
|
|
const GuestSigaction undefinedFlags{callback, flags, {}};
|
|
*__error_nid_postfix() = 0;
|
|
Require(sigaction_nid_postfix(15, &undefinedFlags, nullptr) == -1 && *__error_nid_postfix() == 22);
|
|
Require(sigaction_nid_postfix(15, nullptr, ¤t) == 0 && current.handler == 0 && current.flags == 0x2);
|
|
}
|
|
const GuestSigaction ignoredWithFlags{1, 0x8000, {}};
|
|
Require(sigaction_nid_postfix(15, &ignoredWithFlags, nullptr) == 0);
|
|
Require(sigaction_nid_postfix(15, &defaults, nullptr) == 0);
|
|
|
|
const GuestSigaction crash{infoCallback, 0x40 | 0x10, {}};
|
|
for (int recorded : {10, 1, 64, 128}) {
|
|
Require(sigaction_nid_postfix(recorded, &crash, nullptr) == 0);
|
|
Require(sigaction_nid_postfix(recorded, nullptr, ¤t) == 0);
|
|
Require(Same(current, crash));
|
|
Require(sigaction_nid_postfix(recorded, &defaults, nullptr) == 0);
|
|
}
|
|
Require(sigaction_nid_postfix(6, &crash, nullptr) == 0);
|
|
bool rejected = false;
|
|
try {
|
|
raise_nid_postfix(6);
|
|
|
|
} catch (const std::runtime_error&) {
|
|
rejected = true;
|
|
}
|
|
Require(rejected);
|
|
Require(sigaction_nid_postfix(6, &defaults, ¤t) == 0 && current.handler == infoCallback && current.flags == 0x50);
|
|
|
|
*__error_nid_postfix() = 0;
|
|
Require(sigaction_nid_postfix(0, nullptr, ¤t) == -1 && *__error_nid_postfix() == 22);
|
|
*__error_nid_postfix() = 0;
|
|
Require(sigaction_nid_postfix(129, nullptr, ¤t) == -1 && *__error_nid_postfix() == 22);
|
|
for (int fixed : {9, 17}) {
|
|
*__error_nid_postfix() = 0;
|
|
Require(sigaction_nid_postfix(fixed, &term, ¤t) == -1 && *__error_nid_postfix() == 22);
|
|
Require(sigaction_nid_postfix(fixed, &defaults, ¤t) == 0 && current.handler == 0);
|
|
}
|
|
Require(sigaction_nid_postfix(15, nullptr, nullptr) == 0);
|
|
Require(signal_nid_postfix(15, Callback) != invalid);
|
|
GuestSignalSet termMask{{1u << 14, 0, 0, 0}};
|
|
received = 0;
|
|
Require(sigprocmask_nid_postfix(1, &termMask, nullptr) == 0);
|
|
Require(raise_nid_postfix(15) == 0 && received == 0);
|
|
Require(sigprocmask_nid_postfix(2, &termMask, nullptr) == 0);
|
|
Require(raise_nid_postfix(15) == 0 && received == 15);
|
|
GuestSignalSet urgMask{{1u << 15, 0, 0, 0}};
|
|
received = 0;
|
|
Require(sigprocmask_nid_postfix(1, &urgMask, nullptr) == 0);
|
|
Require(raise_nid_postfix(15) == 0 && received == 15);
|
|
Require(sigprocmask_nid_postfix(2, &urgMask, nullptr) == 0);
|
|
|
|
*__error_nid_postfix() = 0;
|
|
bool nullRejected = false;
|
|
try { sigsuspend_nid_postfix(nullptr); } catch (const std::invalid_argument&) { nullRejected = true; }
|
|
Require(nullRejected);
|
|
Require(signal_nid_postfix(30, Callback) != invalid);
|
|
const GuestSignalSet user{{1u << 29, 0, 0, 0}};
|
|
const GuestSignalSet empty{{0, 0, 0, 0}};
|
|
Require(sigprocmask_nid_postfix(3, &user, &previous) == 0);
|
|
received = 0;
|
|
Require(raise_nid_postfix(30) == 0 && received == 0);
|
|
*__error_nid_postfix() = 0;
|
|
Require(sigsuspend_nid_postfix(&empty) == -1 && *__error_nid_postfix() == 4 && received == 30);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == user.bits[0]);
|
|
Require(signal_nid_postfix(30, MaskCallback) != invalid);
|
|
const GuestSignalSet suspendWithKillAndStop{{(1u << 8) | (1u << 16) | (1u << 28), 0, 0, 0}};
|
|
received = 0;
|
|
Require(raise_nid_postfix(30) == 0 && received == 0);
|
|
Require(sigsuspend_nid_postfix(&suspendWithKillAndStop) == -1 && received == 30);
|
|
Require(maskInHandler.bits[0] == ((1u << 28) | (1u << 29)));
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == user.bits[0]);
|
|
Require(signal_nid_postfix(30, Callback) != invalid);
|
|
received = 0;
|
|
SuspendWait wait{&empty, 0, 0};
|
|
Pthread suspender = nullptr;
|
|
Require(scePthreadCreate(&suspender, nullptr, SuspendEntry, &wait, nullptr) == 0);
|
|
SuspendSender sender{suspender, -1};
|
|
Pthread senderThread = nullptr;
|
|
Require(scePthreadCreate(&senderThread, nullptr, SuspendSend, &sender, nullptr) == 0);
|
|
Require(scePthreadJoin(senderThread, nullptr) == 0 && sender.result == 0);
|
|
Require(scePthreadJoin(suspender, nullptr) == 0);
|
|
Require(wait.result == -1);
|
|
Require(wait.error == 4);
|
|
Require(received == 30);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && previous.bits[0] == user.bits[0]);
|
|
Require(sigprocmask_nid_postfix(2, &user, nullptr) == 0);
|
|
const GuestSignalSet highBlock{{1u << 29, 1u << 7, 0, 0}};
|
|
const GuestSignalSet suspendMask{{0, 0, 1u << 8, 0}};
|
|
Require(sigprocmask_nid_postfix(3, &highBlock, nullptr) == 0);
|
|
Require(signal_nid_postfix(73, Callback) != invalid);
|
|
received = 0;
|
|
SuspendWait highWait{&suspendMask, 0, 0};
|
|
Pthread highSuspender = nullptr;
|
|
Require(scePthreadCreate(&highSuspender, nullptr, SuspendEntry, &highWait, nullptr) == 0);
|
|
SuspendSender highSender{highSuspender, -1};
|
|
Pthread highSenderThread = nullptr;
|
|
Require(scePthreadCreate(&highSenderThread, nullptr, SuspendSend, &highSender, nullptr) == 0);
|
|
Require(scePthreadJoin(highSenderThread, nullptr) == 0 && highSender.result == 0);
|
|
Require(scePthreadJoin(highSuspender, nullptr) == 0);
|
|
Require(highWait.result == -1 && highWait.error == 4 && received == 30);
|
|
Require(sigprocmask_nid_postfix(1, nullptr, &previous) == 0 && std::memcmp(&previous, &highBlock, sizeof(highBlock)) == 0);
|
|
Require(sigprocmask_nid_postfix(3, &empty, nullptr) == 0);
|
|
Require(signal_nid_postfix(73, nullptr) == Callback);
|
|
signal_nid_postfix(30, nullptr);
|
|
|
|
Require(GuestAlarm_nid_no_patch(0) == 0);
|
|
Require(GuestAlarm_nid_no_patch(5) == 0);
|
|
Require(GuestAlarm_nid_no_patch(3) == 5);
|
|
Require(GuestAlarm_nid_no_patch(0) == 3);
|
|
Require(GuestAlarm_nid_no_patch(0) == 0);
|
|
const GuestSigaction ignoreAlarm{1, 0, {}};
|
|
Require(sigaction_nid_postfix(14, &ignoreAlarm, nullptr) == 0);
|
|
Require(GuestAlarm_nid_no_patch(1) == 0);
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
|
|
Require(GuestAlarm_nid_no_patch(0) == 0);
|
|
for (int unmapped : {1, 12, 30, 31, 32, 128}) {
|
|
*__error_nid_postfix() = 0;
|
|
Require(signal_nid_postfix(unmapped, ignore) == nullptr);
|
|
Require(sigaction_nid_postfix(unmapped, nullptr, ¤t) == 0 && current.handler == 1 && current.flags == 0x2);
|
|
Require(signal_nid_postfix(unmapped, Callback) == ignore);
|
|
Require(sigaction_nid_postfix(unmapped, nullptr, ¤t) == 0 && current.handler == callback && current.flags == 0x2);
|
|
Require(signal_nid_postfix(unmapped, nullptr) == Callback);
|
|
}
|
|
for (int outOfRange : {0, 129, -1}) {
|
|
*__error_nid_postfix() = 0;
|
|
Require(signal_nid_postfix(outOfRange, nullptr) == invalid && *__error_nid_postfix() == 22);
|
|
*__error_nid_postfix() = 0;
|
|
Require(signal_nid_postfix(outOfRange, Callback) == invalid && *__error_nid_postfix() == 22);
|
|
}
|
|
for (int fixed : {9, 17}) {
|
|
const GuestSigaction flagged{0, 0x1 | 0x4, {{0x5, 0x6, 0x7, 0x80000000u}}};
|
|
Require(sigaction_nid_postfix(fixed, &flagged, nullptr) == 0);
|
|
*__error_nid_postfix() = 0;
|
|
Require(signal_nid_postfix(fixed, Callback) == invalid && *__error_nid_postfix() == 22);
|
|
*__error_nid_postfix() = 0;
|
|
Require(signal_nid_postfix(fixed, ignore) == invalid && *__error_nid_postfix() == 22);
|
|
*__error_nid_postfix() = 0;
|
|
Require(signal_nid_postfix(fixed, invalid) == invalid && *__error_nid_postfix() == 22);
|
|
Require(sigaction_nid_postfix(fixed, nullptr, ¤t) == 0 && current.handler == 0);
|
|
*__error_nid_postfix() = 12345;
|
|
Require(signal_nid_postfix(fixed, nullptr) == nullptr && *__error_nid_postfix() == 12345);
|
|
Require(sigaction_nid_postfix(fixed, nullptr, ¤t) == 0 && current.handler == 0 && current.flags == 0x2 && current.mask.bits[0] == 0);
|
|
Require(sigaction_nid_postfix(fixed, &defaults, nullptr) == 0);
|
|
}
|
|
{
|
|
const GuestSigaction masked{callback, 0x1 | 0x4, {{0x5, 0x6, 0x7, 0x80000000u}}};
|
|
Require(sigaction_nid_postfix(13, &masked, nullptr) == 0);
|
|
*__error_nid_postfix() = 12345;
|
|
Require(signal_nid_postfix(13, ignore) == Callback && *__error_nid_postfix() == 12345);
|
|
Require(sigaction_nid_postfix(13, nullptr, ¤t) == 0);
|
|
Require(current.handler == 1 && current.flags == 0x2 && current.mask.bits[0] == 0 && current.mask.bits[1] == 0 && current.mask.bits[2] == 0 && current.mask.bits[3] == 0);
|
|
Require(sigaction_nid_postfix(13, &masked, nullptr) == 0);
|
|
Require(signal_nid_postfix(13, Callback) == Callback);
|
|
Require(sigaction_nid_postfix(13, nullptr, ¤t) == 0);
|
|
Require(current.handler == callback && current.flags == 0x2 && current.mask.bits[3] == 0);
|
|
}
|
|
Require(signal_nid_postfix(13, invalid) == Callback);
|
|
Require(sigaction_nid_postfix(13, nullptr, ¤t) == 0 && current.handler == static_cast<std::uintptr_t>(-1) && current.flags == 0x2);
|
|
Require(signal_nid_postfix(13, nullptr) == invalid);
|
|
Require(sigaction_nid_postfix(13, nullptr, ¤t) == 0 && current.handler == 0);
|
|
*__error_nid_postfix() = 0;
|
|
Require(sigpending_nid_postfix(nullptr) == -1);
|
|
Require(*__error_nid_postfix() == 14);
|
|
*__error_nid_postfix() = 42;
|
|
GuestSignalSet pendingSignals{{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}};
|
|
Require(sigpending_nid_postfix(&pendingSignals) == 0);
|
|
Require(pendingSignals.bits[0] == 0 && pendingSignals.bits[1] == 0 && pendingSignals.bits[2] == 0 && pendingSignals.bits[3] == 0);
|
|
Require(*__error_nid_postfix() == 42);
|
|
Require(signal_nid_postfix(15, nullptr) == Callback);
|
|
Require(signal_nid_postfix(15, Callback) == nullptr);
|
|
received = 0;
|
|
Require(sigprocmask_nid_postfix(1, &termMask, nullptr) == 0);
|
|
Require(raise_nid_postfix(15) == 0 && received == 0);
|
|
pendingSignals = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}};
|
|
Require(sigpending_nid_postfix(&pendingSignals) == 0);
|
|
Require(pendingSignals.bits[0] == (1u << 14) && pendingSignals.bits[1] == 0 && pendingSignals.bits[2] == 0 && pendingSignals.bits[3] == 0);
|
|
Require(sigprocmask_nid_postfix(2, &termMask, nullptr) == 0 && received == 15);
|
|
Require(sigpending_nid_postfix(&pendingSignals) == 0);
|
|
Require(pendingSignals.bits[0] == 0 && pendingSignals.bits[1] == 0 && pendingSignals.bits[2] == 0 && pendingSignals.bits[3] == 0);
|
|
Require(signal_nid_postfix(15, nullptr) == Callback);
|
|
|
|
const GuestSignalSet highSignals{{0, 1u << 7, 1u << 8, 1u << 31}};
|
|
for (int guest : {40, 73, 128}) Require(signal_nid_postfix(guest, Callback) != invalid);
|
|
received = 0;
|
|
GuestSignalSet previousHighSignals{};
|
|
Require(sigprocmask_nid_postfix(1, &highSignals, &previousHighSignals) == 0);
|
|
Require(previousHighSignals.bits[0] == 0 && previousHighSignals.bits[1] == 0 &&
|
|
previousHighSignals.bits[2] == 0 && previousHighSignals.bits[3] == 0);
|
|
for (int guest : {40, 73, 128}) Require(raise_nid_postfix(guest) == 0 && received == 0);
|
|
Require(sigpending_nid_postfix(&pendingSignals) == 0 &&
|
|
std::memcmp(&pendingSignals, &highSignals, sizeof(highSignals)) == 0);
|
|
Require(sigprocmask_nid_postfix(2, &highSignals, &previousHighSignals) == 0);
|
|
Require(std::memcmp(&previousHighSignals, &highSignals, sizeof(highSignals)) == 0);
|
|
Require(received == 128);
|
|
Require(sigpending_nid_postfix(&pendingSignals) == 0 &&
|
|
pendingSignals.bits[0] == 0 && pendingSignals.bits[1] == 0 &&
|
|
pendingSignals.bits[2] == 0 && pendingSignals.bits[3] == 0);
|
|
for (int guest : {40, 73, 128}) Require(signal_nid_postfix(guest, nullptr) == Callback);
|
|
for (const int ignoredByDefault : {16, 19, 20, 23, 28, 29}) {
|
|
*__error_nid_postfix() = 0;
|
|
received = 0;
|
|
Require(raise_nid_postfix(ignoredByDefault) == 0 && received == 0 && *__error_nid_postfix() == 0);
|
|
Require(kill_nid_postfix(getpid_nid_postfix(), ignoredByDefault) == 0 && *__error_nid_postfix() == 0);
|
|
}
|
|
const GuestSignalSet ignoredByDefaultSet{{(1u << 15) | (1u << 19) | (1u << 22) | (1u << 27) | (1u << 28), 0, 0, 0}};
|
|
GuestSignalSet pendingIgnored{};
|
|
Require(sigprocmask_nid_postfix(3, &ignoredByDefaultSet, nullptr) == 0);
|
|
for (const int ignoredByDefault : {16, 20, 23, 28, 29}) Require(raise_nid_postfix(ignoredByDefault) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == 0);
|
|
const GuestSignalSet noneBlocked{{0, 0, 0, 0}};
|
|
Require(sigprocmask_nid_postfix(3, &noneBlocked, nullptr) == 0);
|
|
const GuestSigaction ignored{1, 0, {}};
|
|
const GuestSigaction restored{0, 0, {}};
|
|
const GuestSignalSet userSignal{{1u << 29, 0, 0, 0}};
|
|
Require(sigaction_nid_postfix(30, &ignored, nullptr) == 0);
|
|
*__error_nid_postfix() = 0;
|
|
Require(raise_nid_postfix(30) == 0 && kill_nid_postfix(getpid_nid_postfix(), 30) == 0 && *__error_nid_postfix() == 0);
|
|
Require(sigprocmask_nid_postfix(3, &userSignal, nullptr) == 0);
|
|
Require(raise_nid_postfix(30) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == 0);
|
|
Require(sigprocmask_nid_postfix(3, &noneBlocked, nullptr) == 0);
|
|
Require(sigaction_nid_postfix(30, &restored, nullptr) == 0);
|
|
|
|
const GuestSigaction caught{callback, 0, {}};
|
|
received = 0;
|
|
Require(sigaction_nid_postfix(30, &caught, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(3, &userSignal, nullptr) == 0);
|
|
Require(raise_nid_postfix(30) == 0 && received == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == userSignal.bits[0]);
|
|
Require(sigaction_nid_postfix(30, &restored, nullptr) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == userSignal.bits[0]);
|
|
Require(sigaction_nid_postfix(30, &ignored, nullptr) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == 0);
|
|
Require(sigaction_nid_postfix(30, &caught, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(3, &noneBlocked, nullptr) == 0 && received == 0);
|
|
Require(sigprocmask_nid_postfix(3, &userSignal, nullptr) == 0);
|
|
Require(raise_nid_postfix(30) == 0 && received == 0);
|
|
Require(signal_nid_postfix(30, ignore) == Callback);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == 0);
|
|
Require(signal_nid_postfix(30, Callback) == ignore);
|
|
Require(sigprocmask_nid_postfix(3, &noneBlocked, nullptr) == 0 && received == 0);
|
|
Require(signal_nid_postfix(30, nullptr) == Callback);
|
|
|
|
const GuestSignalSet windowSignal{{1u << 27, 0, 0, 0}};
|
|
Require(sigaction_nid_postfix(28, &caught, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(3, &windowSignal, nullptr) == 0);
|
|
Require(raise_nid_postfix(28) == 0 && received == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == windowSignal.bits[0]);
|
|
Require(sigaction_nid_postfix(28, &restored, nullptr) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == 0);
|
|
Require(sigaction_nid_postfix(28, &caught, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(3, &noneBlocked, nullptr) == 0 && received == 0);
|
|
Require(sigaction_nid_postfix(28, &restored, nullptr) == 0);
|
|
|
|
const GuestSignalSet continueSignal{{1u << 18, 0, 0, 0}};
|
|
Require(sigprocmask_nid_postfix(3, &continueSignal, nullptr) == 0);
|
|
Require(raise_nid_postfix(19) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == continueSignal.bits[0]);
|
|
Require(signal_nid_postfix(19, nullptr) == nullptr);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == 0);
|
|
Require(sigprocmask_nid_postfix(3, &noneBlocked, nullptr) == 0 && received == 0);
|
|
|
|
const GuestSignalSet highSignal{{0, 1u << 7, 0, 0}};
|
|
Require(sigprocmask_nid_postfix(3, &highSignal, nullptr) == 0);
|
|
Require(raise_nid_postfix(40) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[1] == highSignal.bits[1]);
|
|
Require(sigaction_nid_postfix(40, &ignored, nullptr) == 0);
|
|
Require(sigpending_nid_postfix(&pendingIgnored) == 0 && pendingIgnored.bits[0] == 0 && pendingIgnored.bits[1] == 0);
|
|
Require(sigaction_nid_postfix(40, &restored, nullptr) == 0);
|
|
Require(sigprocmask_nid_postfix(3, &noneBlocked, nullptr) == 0);
|
|
Require(_sigintr_nid_postfix.bits[0] == 0 && _sigintr_nid_postfix.bits[1] == 0 && _sigintr_nid_postfix.bits[2] == 0 &&
|
|
_sigintr_nid_postfix.bits[3] == 0);
|
|
GuestSigaction interruptible{};
|
|
Require(signal_nid_postfix(30, Callback) == nullptr);
|
|
Require(sigaction_nid_postfix(30, nullptr, &interruptible) == 0 && interruptible.flags == 0x2);
|
|
_sigintr_nid_postfix.bits[0] = 1u << 29;
|
|
Require(signal_nid_postfix(30, Callback) == Callback);
|
|
Require(sigaction_nid_postfix(30, nullptr, &interruptible) == 0 &&
|
|
interruptible.handler == reinterpret_cast<std::uintptr_t>(Callback) && interruptible.flags == 0);
|
|
signal_nid_postfix(31, Callback);
|
|
|
|
Require(sigaction_nid_postfix(31, nullptr, &interruptible) == 0 && interruptible.flags == 0x2);
|
|
_sigintr_nid_postfix.bits[3] = 1u << 31;
|
|
Require(signal_nid_postfix(128, Callback) == nullptr);
|
|
Require(sigaction_nid_postfix(128, nullptr, &interruptible) == 0 && interruptible.flags == 0);
|
|
_sigintr_nid_postfix.bits[0] = 0;
|
|
_sigintr_nid_postfix.bits[3] = 0;
|
|
Require(signal_nid_postfix(30, Callback) == Callback);
|
|
Require(sigaction_nid_postfix(30, nullptr, &interruptible) == 0 && interruptible.flags == 0x2);
|
|
Require(signal_nid_postfix(30, nullptr) == Callback && signal_nid_postfix(31, nullptr) == Callback &&
|
|
signal_nid_postfix(128, nullptr) == Callback);
|
|
Require(signal_nid_postfix(30, Callback) == nullptr);
|
|
Require(siginterrupt_nid_postfix(30, 1) == 0 && _sigintr_nid_postfix.bits[0] == (1u << 29));
|
|
Require(sigaction_nid_postfix(30, nullptr, &interruptible) == 0 &&
|
|
interruptible.handler == reinterpret_cast<std::uintptr_t>(Callback) && interruptible.flags == 0);
|
|
Require(signal_nid_postfix(30, Callback) == Callback);
|
|
Require(sigaction_nid_postfix(30, nullptr, &interruptible) == 0 && interruptible.flags == 0);
|
|
Require(siginterrupt_nid_postfix(30, 0) == 0 && _sigintr_nid_postfix.bits[0] == 0);
|
|
Require(sigaction_nid_postfix(30, nullptr, &interruptible) == 0 &&
|
|
interruptible.handler == reinterpret_cast<std::uintptr_t>(Callback) && interruptible.flags == 0x2);
|
|
Require(siginterrupt_nid_postfix(128, 1) == 0 && _sigintr_nid_postfix.bits[3] == (1u << 31));
|
|
Require(sigaction_nid_postfix(128, nullptr, &interruptible) == 0 && interruptible.handler == 0 && interruptible.flags == 0);
|
|
Require(siginterrupt_nid_postfix(128, 0) == 0 && _sigintr_nid_postfix.bits[3] == 0);
|
|
Require(sigaction_nid_postfix(128, nullptr, &interruptible) == 0 && interruptible.flags == 0x2);
|
|
for (const int badSignal : {0, -1, 129}) {
|
|
*__error_nid_postfix() = 0;
|
|
Require(siginterrupt_nid_postfix(badSignal, 1) == -1 && *__error_nid_postfix() == 22);
|
|
}
|
|
Require(_sigintr_nid_postfix.bits[0] == 0 && _sigintr_nid_postfix.bits[3] == 0);
|
|
Require(signal_nid_postfix(30, nullptr) == Callback);
|
|
Require(sigaction_nid_postfix(128, &restored, nullptr) == 0);
|
|
}
|