siginterrupt is a libSceLibcInternal export (the public SDK's stub table has it there, not in the
kernel tables) and FreeBSD 11.4's lib/libc/gen/siginterrupt.c reads the signal's disposition,
sets or clears the signal's bit in _sigintr and SA_RESTART, and installs the disposition again.
libc cannot call libkernel, so, as the pthread hooks do, libc keeps a registered sigaction and
the address of the _sigintr set, and libkernel registers both from a static initializer when it
loads. A call before that throws; the set is written without libkernel's registration lock, as
FreeBSD's libc does. Builds on #8866, which adds the set.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The public SDK's libkernel, libkernel_sys and libkernel_web stub tables declare _sigintr, the
sigset_t that FreeBSD's libc shares between signal and siginterrupt, and no built library
provided it (#8846). libkernel now exports the 16-byte object, zero at start, and signal records
a handler with SA_RESTART unless its signal is in the set, as lib/libc/gen/signal.c does.
siginterrupt, which fills the set, is a libSceLibcInternal export; libc does not link libkernel
and cannot reach the dispositions, so it stays out and a debt entry for signal says so.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
When the native open failed with an error other than ENOENT, OpenNative
probed whether the path is a directory with std::filesystem::is_directory.
With the MinGW runtime that probe can set errno to ENOENT, and OpenNative
then reported the probe's ENOENT instead of the open error. On Windows 11
22621 a symbolic link loop failed with ELOOP from the native open and
sceKernelOpen returned 0x80020002, so guest_filesystem aborted at the
ELOOP check added by #8640.
Keep the open error and restore it when the path is not a directory.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
pthread_kill(thread, 0) returned 0 for every handle other than the caller's before it asked whether the thread was still alive. FreeBSD's _pthread_kill looks the thread up with _thr_find_thread before it checks for signal 0, so the call answers ESRCH for a thread that has ended or was never a thread. The liveness check now runs before the signal 0 shortcut; the calling thread still answers 0.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Since #8512 a raise redirects a target running host code once 50 ms have
passed since the raise began. A target inside a system call that is not a
wait, such as the NtWriteFile of an fwrite that holds its stream lock, can
stay there longer; the redirect then ran the handler with the lock held.
SONIC SUPERSTARS froze at frame 67 again on main this way, with its GC
raise delivered at ntdll!ZwWriteFile+20.
A target stopped right after a syscall instruction in ntdll now restarts
the 50 ms host-code window, so the raise keeps sampling until the call
returns and the target leaves host code, bounded by the 1 s retry limit.
guest_raise_in_system_call holds a writer in NtWriteFile on a slowly
drained pipe; it times out on main and passes with this change.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Animal Well (PPSA22520) imports _Thrd_detach (L7f7zYwBvZA) from libc.prx and nothing exports it, so the Windows loader stops at startup. Register libkernel's pthread_detach with libc like pthread_create and pthread_join, and return _Thrd_error (4) when it fails.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GtXavMkgCTCdmRpweviHcQ
Culprit: none in 892a4f1328..b85d972f42; race in the Windows vnode watch (50b06110b guarded only the loop). Run 39473930499, guest_kqueue: a watched file deleted before registration is snapshotted under $Extend\$Deleted, WatchParent got ERROR_ACCESS_DENIED and threw.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The Windows sceKernelGetdirentries stored 0 in *basep on every read, so a
guest looping on the cookie saw it stall (FreeBSD stores the directory
offset the read started at, kern_getdirentries: *basep = loff). Report the
index of the first entry of the read, the same unit lseek takes on these
descriptors, and run guest_directory_entries on Windows, where it was never
built.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
kevent threw NotImplemented for EVFILT_WRITE with NOTE_LOWAT above 1 on a socket, although the socket readiness check already reports free send-buffer space (SO_SNDBUF less SIOCOUTQ on Linux). The write event now fires once that space reaches the mark, as FreeBSD 11's filt_sowrite compares sbspace with kn_sdata, and stays silent while the space is below it. The debt entry no longer says a write mark is limited to 1. Reference: https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/kern/uipc_socket.c
On Windows, utimes, lutimes, sceKernelUtimes and futimes open a
FILE_WRITE_ATTRIBUTES handle and only then encode the times. A time the
host cannot represent returned EINVAL without calling SetFileTime, and
with NTFS last-access updates enabled closing that handle set the file's
access time to the current time, so a rejected call still changed the
file and guest_file_timestamps failed on "access time preserves
microseconds". A rejected time now marks the handle with 0xFFFFFFFF,
which SetFileTime documents as preventing operations on the handle from
updating the times, before the handle is closed. Error order is
unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>