A socket EVFILT_READ knote whose NOTE_LOWAT mark is below 1 is now always ready and reports the bytes in the receive buffer, 0 when it is empty, because FreeBSD 11.4 filt_soread returns kn_data >= kn_sdata and the bytes available are never negative. This holds for level-triggered and EV_CLEAR knotes and when EV_ADD changes the mark of an existing knote. A listening socket ignores the mark, as filt_solisten does. An EVFILT_WRITE mark below 1 still throws.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Keep both EVFILT_PROC (main) and EVFILT_SIGNAL (this PR) in Kqueue.cpp: the constants, the two knote functions, the filter check and the dispatch. Debt doc: main's EVFILT_PROC and pipe wording with the PR's signal text.
On Windows a pair is a loopback stream or two connected datagram sockets
rather than the console's local pair. After the peer closes, the first
stream send reaches a socket the host still accepts and succeeds, where
the console fails it with EPIPE, and an empty datagram receive waits on a
socket the host never signals, where the console fails it with
ECONNRESET; a datagram queued before the close is still delivered first.
Both answers now come from the pair's lost peer before the host is
waited on. Measured on a PS5 (13.60 and 11.60): send EPIPE (32) and
receive ECONNRESET (54).
The receive side asks the socket whether a datagram is queued rather than
whether bytes are queued, because a datagram sent with no payload still
has to be delivered: ioctlsocket answers 1 for one on this host, and
select answers readable, while a byte count of the socket as a whole
would answer 0 on a host that counts payload only. The Windows case now
sends an empty datagram before the close and expects it, then 54.
The FreeBSD permalink in the pthread_barrier debt entry covered _pthread_barrier_destroy; the count check it describes is at lines 97 to 104.
Co-authored-by: slopgobblercobbler <[email protected]>
ProsperoWeb (PRWB00001) 0.2.1 imports the three from libkernel. Only
libkernel_sys exported them, and a Linux run of the title does not load
libkernel_sys.prx, so the loader stopped with "undefined symbol:
LxIacrWiJ3w" before the title started.
Cpuset.cpp moves to libkernel whole, because cpuset and cpuset_setid
share its set table with cpuset_getid; its test and debt entry follow.
rfork_thread and sceKernelRdup move with the prototypes the title uses
and still throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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
On macOS under Rosetta, Aps5StartGuest moves the main thread off the host
stack and releases the old range to the guest arena. dyld keeps its own
pointers into the process start block at the top of that range and offers
no call that redirects them, where argv and environ have one:
_NSGetExecutablePath copies the path string out of the block on every
call, so the first call after the move read unmapped memory and the
process died with KERN_PROTECTION_FAILURE. A title does not have to call
it: libxpc reaches it from xpc_connection_resume, and ShaderCacheDirectory
calls it for the shader disk cache.
Release the old stack only up to the pages that hold the block, and only
while argv still points into the stack. They are the top two pages, 8 KiB
of the 8372224-byte stack here, so a title that fixes a mapping over that
range now fails with a host region overlap; the rest is free as before.
guest_main_stack_move asked for a 64 KiB guest mapping aligned down from
a local of main, which falls inside the kept pages. It now probes the
64 KiB below them, requires the kept pages to be refused, and calls
_NSGetExecutablePath after the move, which segfaults without this change.
The release archives carry mimalloc's binaries on Linux and Windows, so
they now also carry its MIT licence as libs/licenses/mimalloc.txt, and
packaging fails without it. USAGE.md and ENVIRONMENT.md say that
APS5_MIMALLOC and LD_PRELOAD stay set after the restart and state the
memory cost measured with it, and the restart's debt entry says that
only the log-file copy is handed back before execv.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015W3M6NbYpmwWkzkL8YNLaF