Merge pull request #3430 from AchrafReyani/feat/libkernel-sigtimedwait

feat(libkernel): export sigtimedwait
This commit is contained in:
Adrià 2026-10-11 12:36:53 +02:00 committed by GitHub
commit 6554fcb68a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 0 deletions

View File

@ -517,6 +517,15 @@ if(BUILD_TESTING)
set_tests_properties(guest_signals PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_test_executable(guest_sigtimedwait_tests ${LIBS_INCLUDE_DIR}/tests/GuestSigtimedwait.cpp)
target_include_directories(guest_sigtimedwait_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_sigtimedwait_tests PRIVATE libkernel libc)
configure_windows_unwind(guest_sigtimedwait_tests)
add_test(NAME guest_sigtimedwait COMMAND guest_sigtimedwait_tests)
if(WIN32)
set_tests_properties(guest_sigtimedwait PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_test_executable(guest_parent_process_tests ${LIBS_INCLUDE_DIR}/tests/GuestParentProcess.cpp)
target_include_directories(guest_parent_process_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_parent_process_tests PRIVATE libkernel libc)

View File

@ -249,6 +249,14 @@ int APS5_VABI pthread_sigmask_nid_postfix(int how, const GuestSignalSet* set, Gu
if (set != nullptr && (how < 1 || how > 3)) return 22;
return _sigprocmask_nid_postfix(how, set, previousSet);
}
int APS5_VABI sigtimedwait_nid_postfix(const GuestSignalSet* set, void* info, const void* timeout) {
(void)set;
(void)info;
(void)timeout;
NotImplemented_nid_no_patch("sigtimedwait: waiting for a pending signal");
return -1;
}
}
extern "C" {

View File

@ -0,0 +1,31 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>
#include <cstdlib>
#include <stdexcept>
#include <string>
struct GuestSignalSet {
std::uint32_t bits[4];
};
struct GuestTimespec {
std::int64_t seconds;
std::int64_t nanoseconds;
};
extern "C" int APS5_VABI sigtimedwait_nid_postfix(const GuestSignalSet*, void*, const GuestTimespec*);
static void Require(bool value) { if (!value) std::abort(); }
static bool ReportsNotImplemented(const GuestSignalSet* set, void* info, const GuestTimespec* timeout) {
try {
sigtimedwait_nid_postfix(set, info, timeout);
} catch (const std::runtime_error& error) {
return std::string(error.what()) == "sigtimedwait: waiting for a pending signal not implemented";
}
return false;
}
int main() {
const GuestSignalSet pipe{{1u << 12, 0, 0, 0}};
unsigned char info[64] = {};
const GuestTimespec poll{0, 0};
const GuestTimespec second{1, 0};
Require(ReportsNotImplemented(&pipe, info, &poll));
Require(ReportsNotImplemented(&pipe, nullptr, &second));
Require(ReportsNotImplemented(&pipe, info, nullptr));
}

View File

@ -573,6 +573,7 @@ Throughout the project, every function at every stage either **does exactly what
- [sceVideodec2CreateDecoder](../../core/libs/prx/libSceVideodec2/Export.cpp) (libSceVideodec2) decodes HEVC (codec type 974921) and VP9 (2382845) through FFmpeg, besides H.264. The tags come from SharpProspero's `Videodec2CodecType` and EVO-PLAYER-PS5's `sce_videodec2.h`, which records them from hardware runs. HEVC input is converted from length-prefixed NAL units to Annex B as for H.264, and VP9 frames are passed through. Output is the same 8-bit NV12 for every codec; a decoder for HEVC Main10 or VP9 Profile 2 is created, but a frame deeper than 8 bits throws, since the console's 10-bit output layout is unknown, and `QueryDecoderMemoryInfo` reports the 8-bit frame size for it. `sceVideodec2GetPictureInfo` and `sceVideodec2GetAvcPictureInfo` throw for HEVC and VP9 pictures, which use other layouts (`SceVideodec2HevcPictureInfo`, `SceVideodec2Vp9PictureInfo`), and `sceVideodec2GetHevcPictureInfo` and `sceVideodec2GetVp9PictureInfo` are not exported
- [syslog](../../core/libs/prx/libc/src/Syslog.cpp) (libc) writes each message to `stderr` as `[syslog:<priority>] <message>`, with a newline added when missing, instead of sending it to the console's system log. Priority and facility handling follow FreeBSD's `vsyslog`: `%m` expands to the guest errno's message, unknown bits are reported (as priority 0x23, since FreeBSD passes `LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID` as the priority) and masked, a missing facility becomes `LOG_USER`, and errno is preserved. `openlog`, `setlogmask` and `closelog` are not implemented, so the identity, options and mask they set are not applied
- [daemon](../../core/libs/prx/libc/src/Process.cpp) (libc) throws: forking into the background is not supported. PPSA85300 imports it and fails to load without it. VLC 3.0 calls it only when its `daemon` option is set ([libvlc.c](https://github.com/videolan/vlc/blob/6de05adcbaf2e8b85fe86aad4169393098628119/src/libvlc.c#L190-L197)), and the title starts libVLC with `--ignore-config` and without `--daemon` ([player.cc](https://github.com/ZiZc3/VLC/blob/f3253020a64368153233ede29183014c0b6c8979/src/player.cc#L960-L981))
- [sigtimedwait](../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) throws: guest signals are delivered when raised and never left pending, so there is nothing to wait for or take. PPSA85300 imports it and fails to load without it. Its only call site is VLC's `vlc_writev` ([filesystem.c](https://github.com/videolan/vlc/blob/6de05adcbaf2e8b85fe86aad4169393098628119/src/posix/filesystem.c#L243-L278)), which polls with a zero timeout to drain a `SIGPIPE` only after `writev` fails with `EPIPE`
- [sigaction](../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) records the handler, flags and mask of every signal from 1 to 128 and reports them back, following FreeBSD's `sigaction` (`EINVAL` for other signals, and for a handler on `SIGKILL` or `SIGSTOP`); `signal` records its handler with `SA_RESTART`, as FreeBSD's libc does. Only handlers without `SA_SIGINFO` on the signals `signal` already delivers (`SIGINT`, `SIGILL`, `SIGABRT`, `SIGFPE`, `SIGSEGV`, `SIGTERM`) run, the same way `signal` handlers do; their mask and flags are not applied. `SA_SIGINFO` handlers are recorded but never called, since that needs FreeBSD's `siginfo_t` and `ucontext_t`, and neither are the handlers of other signals (`SIGBUS`, `SIGHUP`, ...), whether they are set by `sigaction` or by `signal`, which records them too (every number from 1 to 128, with `SA_RESTART` and an empty mask replacing what `sigaction` stored; `SIGKILL` and `SIGSTOP` accept only the default handler in both calls, as in FreeBSD's `kern_sigaction`). `raise` of an `SA_SIGINFO` handler on a signal `signal` delivers throws instead of terminating, and `raise` and `kill` of the other signals still fail with `EINVAL`, recorded handler or not
- [kill](../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) follows FreeBSD's `kern_kill` and `killpg1` for the only guest process: `EINVAL` for signals outside 0 to 128, signal 0 only checks that the target exists, and its own pid, 0 and minus its own pid (the guest is taken to lead its own process group) signal it through `raise`, so they share `raise`'s limits above. Any other pid, and -1, which skips the caller, report `ESRCH`, so `EPERM` is never reported
- [sceKernelFcntl](../../core/libs/prx/libkernel/File/src/Open.cpp) (libkernel) handles socket descriptors through the POSIX `fcntl` export (`F_GETFL`, `F_SETFL` with `O_NONBLOCK`) and returns its guest errno as `SCE_KERNEL_ERROR_*`, the form the other `sceKernel` file exports use; the command semantics follow FreeBSD's [fcntl](https://github.com/freebsd/freebsd-src/blob/stable/11/sys/kern/kern_descrip.c), and a closed descriptor returns `SCE_KERNEL_ERROR_EBADF`. File descriptors throw: their open flags are not tracked, and `F_DUPFD`, `F_GETFD` and `F_SETFD` are unsupported on all descriptors. The return values and error codes are unverified on a console