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]>
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]>
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
With APS5_MIMALLOC set, libkernel restarts the title with
libmimalloc.so from libs/ first in LD_PRELOAD, as it does on macOS
with DYLD_INSERT_LIBRARIES. The macOS restart becomes one
implementation with platform pieces (MimallocRestart.cpp): on Linux
the executable is the target of /proc/self/exe and the arguments
those of /proc/self/cmdline. The restart is a priority 101
constructor, so it runs before libkernel's other initializers. It
gives the standard streams back from an ANYPS5_LOG_FILE copy before
execv, which also fixes the macOS restart under that variable, and
refuses a path the preload list cannot hold.
The build copies libmimalloc.so beside the libraries except in ASan
and TSan builds, the Linux release archives ship it, and the restart
tests run on Linux too, with a new case for ANYPS5_LOG_FILE.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015W3M6NbYpmwWkzkL8YNLaF
Cut the two longest exception handler entries under the 1000 character
limit: the mapping entry keeps the unverified protection fault signal and
what counts as title code, the Linux entry keeps what a later guest signal,
the conversion stubs and older glibc change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
dladdr1 searches the object's symbol table, which made every host fault
chained past an installed handler about 8 us slower on Linux. glibc 2.35
and later answer the same question with _dl_find_object, which is also
async-signal-safe; older glibc keeps dladdr1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A handler that returns the context unchanged runs again on the same fault,
a handler that fixes the page with mprotect and returns lets the store
complete, and a handler that removes itself and returns ends the process
with the fault (checked in a child process, so a loop fails on a timeout).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A handler installed for SIGILL, SIGFPE, SIGBUS or SIGSEGV now receives
the faults raised in title code instead of the process ending, with
mc_trapno, mc_addr and mc_err filled as FreeBSD 11's amd64 trap() does.
On Windows the crash reporter's vectored handler offers unclaimed faults
to libkernel, which redirects the thread to a stub that runs the handler
outside the exception dispatcher; on Linux chained host signal handlers
classify faults by REG_TRAPNO.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolves docs/dev/debt/libkernel.md: main's sigaction entry (SIGPIPE outside Windows) and this branch's signal entry, which points to libSceLibcInternal for siginterrupt.
Co-Authored-By: Claude Opus 5.5 <[email protected]>