Lib.Kernel: Various (mostly signal-related) fixes (#4463)

* sigaddset, sigdelset, sigismember

* Some define fixups

Based on decomp, PS4 sigset is defined as a u32[4]. This doesn't change any behavior, but makes my decomp-based sigaddset and sigdelset implementations function appropriately.
Additionally, define handler and sigaction functions as PS4_SYSV_ABI.

* Fix returns

* Implement signal, export _sigintr

In libkernel, signal just uses sigaction. No harm in implementing it, since we've got our own implementations for everything except sigaction (and sigaction is implemented for Unix platforms).

* Fix and cleanup posix_select defines

Swaps use of defines for just having static functions, and fixes the pd_set_posix struct to match FreeBSD/Orbis properly (sizeof(long) == 4 on Windows, which does not match Orbis).

* Fix siginfo struct

Again, sizeof(long) differs on different platforms. Need to use our proper typedef to ensure accuracy.

* Clang, the bane of my existance.

* Oops
This commit is contained in:
Stephen Miller
2026-05-25 02:27:55 -05:00
committed by GitHub
parent 9dada49956
commit 86a64fb980
3 changed files with 93 additions and 30 deletions
+13 -12
View File
@@ -1223,25 +1223,26 @@ s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) {
}
#ifdef _WIN32
#define __FD_SETSIZE 1024
typedef struct {
unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(unsigned long))];
u64 fds_bits[16];
} fd_set_posix;
#define FD_SET_POSIX(fd, set) \
((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] |= \
(1UL << ((fd) % (8 * sizeof(unsigned long)))))
static void FD_SET_POSIX(s32 fd, fd_set_posix* set) {
set->fds_bits[fd / (8 * sizeof(u64))] |= (1ULL << (fd % (8 * sizeof(u64))));
}
#define FD_CLR_POSIX(fd, set) \
((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] &= \
~(1UL << ((fd) % (8 * sizeof(unsigned long)))))
static void FD_CLR_POSIX(s32 fd, fd_set_posix* set) {
set->fds_bits[fd / (8 * sizeof(u64))] &= ~(1ULL << (fd % (8 * sizeof(u64))));
}
#define FD_ISSET_POSIX(fd, set) \
(((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] & \
(1UL << ((fd) % (8 * sizeof(unsigned long))))) != 0)
static bool FD_ISSET_POSIX(s32 fd, fd_set_posix* set) {
return (set->fds_bits[fd / (8 * sizeof(u64))] & (1ULL << (fd % (8 * sizeof(u64))))) != 0;
}
#define FD_ZERO_POSIX(set) memset((set), 0, sizeof(fd_set_posix))
static void FD_ZERO_POSIX(fd_set_posix* set) {
std::memset(set, 0, sizeof(fd_set_posix));
}
s32 PS4_SYSV_ABI posix_select(s32 nfds, fd_set_posix* readfds, fd_set_posix* writefds,
fd_set_posix* exceptfds, OrbisKernelTimeval* timeout) {
@@ -187,6 +187,7 @@ s32 OrbisToNativeSignal(s32 s) {
#endif
std::array<OrbisKernelExceptionHandler, 130> Handlers{};
Sigset g_sigintr{};
#ifndef _WIN64
void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context) {
@@ -301,17 +302,50 @@ void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) {
s32 PS4_SYSV_ABI posix_sigemptyset(Sigset* s) {
s->bits[0] = 0;
s->bits[1] = 0;
return 0;
s->bits[2] = 0;
s->bits[3] = 0;
return ORBIS_OK;
}
s32 PS4_SYSV_ABI posix_sigfillset(Sigset* s) {
s->bits[0] = ~0U;
s->bits[1] = ~0U;
return 0;
s->bits[2] = ~0U;
s->bits[3] = ~0U;
return ORBIS_OK;
}
s32 PS4_SYSV_ABI posix_sigaddset(Sigset* s, s32 sig) {
s32 val = sig - 1;
if (val >= 0x80) {
*Libraries::Kernel::__Error() = POSIX_EINVAL;
return ORBIS_FAIL;
}
s->bits[val >> 5] |= 1 << (val & 0x1f);
return ORBIS_OK;
}
s32 PS4_SYSV_ABI posix_sigdelset(Sigset* s, s32 sig) {
s32 val = sig - 1;
if (val >= 0x80) {
*Libraries::Kernel::__Error() = POSIX_EINVAL;
return ORBIS_FAIL;
}
s->bits[val >> 5] &= ~(1 << (val & 0x1f));
return ORBIS_OK;
}
s32 PS4_SYSV_ABI posix_sigismember(Sigset* s, s32 sig) {
s32 val = sig - 1;
if (val >= 0x80) {
*Libraries::Kernel::__Error() = POSIX_EINVAL;
return ORBIS_FAIL;
}
return ((s->bits[val >> 5] >> (val & 0x1f)) & 1) != 0;
}
bool PS4_SYSV_ABI posix_sigisemptyset(Sigset* s) {
return s->bits[0] == 0 && s->bits[1] == 0;
return s->bits[0] == 0 && s->bits[1] == 0 && s->bits[2] == 0 && s->bits[3] == 0;
}
s32 PS4_SYSV_ABI posix_sigprocmask(s32 how, const Sigset* set, Sigset* oset) {
@@ -412,6 +446,22 @@ s32 PS4_SYSV_ABI posix_sigaction(s32 sig, Sigaction* act, Sigaction* oact) {
return ORBIS_OK;
}
SigHandler PS4_SYSV_ABI posix_signal(s32 sig, SigHandler func) {
Sigaction act{};
act.__sigaction_handler.handler = func;
posix_sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (posix_sigismember(&g_sigintr, sig) == 0) {
act.sa_flags |= POSIX_SA_RESTART;
}
Sigaction oact{};
s32 result = posix_sigaction(sig, &act, &oact);
if (result >= ORBIS_OK) {
return oact.__sigaction_handler.handler;
}
return reinterpret_cast<SigHandler>(-1);
}
s32 PS4_SYSV_ABI posix_pthread_kill(PthreadT thread, s32 sig) {
if (sig < 1 || sig > 128) { // off-by-one error?
return POSIX_EINVAL;
@@ -515,6 +565,8 @@ s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(s32 error, s64 unk) {
}
void RegisterException(Core::Loader::SymbolsResolver* sym) {
LIB_OBJ("nQVWJEGHObc", "libkernel", 1, "libkernel", &g_sigintr);
LIB_FUNCTION("il03nluKfMk", "libkernel_unity", 1, "libkernel", sceKernelRaiseException);
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel",
sceKernelInstallExceptionHandler);
@@ -526,15 +578,23 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel", 1, "libkernel", sceKernelRemoveExceptionHandler);
LIB_FUNCTION("KiJEPEWRyUY", "libkernel", 1, "libkernel", posix_sigaction);
LIB_FUNCTION("VADc3MNQ3cM", "libkernel", 1, "libkernel", posix_signal);
LIB_FUNCTION("+F7C-hdk7+E", "libkernel", 1, "libkernel", posix_sigemptyset);
LIB_FUNCTION("VkTAsrZDcJ0", "libkernel", 1, "libkernel", posix_sigfillset);
LIB_FUNCTION("JUimFtKe0Kc", "libkernel", 1, "libkernel", posix_sigaddset);
LIB_FUNCTION("Nd-u09VFSCA", "libkernel", 1, "libkernel", posix_sigdelset);
LIB_FUNCTION("JnNl8Xr-z4Y", "libkernel", 1, "libkernel", posix_sigismember);
LIB_FUNCTION("aPcyptbOiZs", "libkernel", 1, "libkernel", posix_sigprocmask);
LIB_FUNCTION("yH-uQW3LbX0", "libkernel", 1, "libkernel", posix_pthread_kill);
LIB_FUNCTION("sHziAegVp74", "libkernel", 1, "libkernel", posix_sigalstack);
LIB_FUNCTION("KiJEPEWRyUY", "libScePosix", 1, "libkernel", posix_sigaction);
LIB_FUNCTION("VADc3MNQ3cM", "libScePosix", 1, "libkernel", posix_signal);
LIB_FUNCTION("+F7C-hdk7+E", "libScePosix", 1, "libkernel", posix_sigemptyset);
LIB_FUNCTION("VkTAsrZDcJ0", "libScePosix", 1, "libkernel", posix_sigfillset);
LIB_FUNCTION("JUimFtKe0Kc", "libScePosix", 1, "libkernel", posix_sigaddset);
LIB_FUNCTION("Nd-u09VFSCA", "libScePosix", 1, "libkernel", posix_sigdelset);
LIB_FUNCTION("JnNl8Xr-z4Y", "libScePosix", 1, "libkernel", posix_sigismember);
LIB_FUNCTION("aPcyptbOiZs", "libScePosix", 1, "libkernel", posix_sigprocmask);
LIB_FUNCTION("yH-uQW3LbX0", "libScePosix", 1, "libkernel", posix_pthread_kill);
LIB_FUNCTION("sHziAegVp74", "libScePosix", 1, "libkernel", posix_sigalstack);
+17 -15
View File
@@ -120,7 +120,7 @@ struct ExStack {
};
struct Sigset {
u64 bits[2];
u32 bits[4];
};
union Sigval {
@@ -133,45 +133,47 @@ union Sigval {
};
struct Siginfo {
int _si_signo; /* signal number */
int _si_errno; /* errno association */
s32 _si_signo; /* signal number */
s32 _si_errno; /* errno association */
/*
* Cause of signal, one of the SI_ macros or signal-specific
* values, i.e. one of the FPE_... values for SIGFPE. This
* value is equivalent to the second argument to an old-style
* FreeBSD signal handler.
*/
int _si_code; /* signal code */
s32 _si_code; /* signal code */
s32 _si_pid; /* sending process */
u32 _si_uid; /* sender's ruid */
int _si_status; /* exit value */
s32 _si_status; /* exit value */
void* _si_addr; /* faulting instruction */
union Sigval _si_value; /* signal value */
union {
struct {
int _trapno; /* machine specific trap code */
s32 _trapno; /* machine specific trap code */
} _fault;
struct {
int _timerid;
int _overrun;
s32 _timerid;
s32 _overrun;
} _timer;
struct {
int _mqd;
s32 _mqd;
} _mesgq;
struct {
long _band; /* band event for SIGPOLL */
} _poll; /* was this ever used ? */
s64 _band; /* band event for SIGPOLL */
} _poll; /* was this ever used ? */
struct {
long __spare1__;
int __spare2__[7];
s64 __spare1__;
s32 __spare2__[7];
} __spare__;
} _reason;
};
using SigHandler = void PS4_SYSV_ABI (*)(int);
struct Sigaction {
union {
void (*handler)(int);
void (*sigaction)(int, struct Siginfo*, void*);
void PS4_SYSV_ABI (*handler)(int);
void PS4_SYSV_ABI (*sigaction)(int, struct Siginfo*, void*);
} __sigaction_handler;
int sa_flags;
Sigset sa_mask;