Repository navigation
fix(libkernel): give guest sockets ordinary descriptor numbers below FD_SETSIZE - #4391
Conversation
f6ca277 to
268dcec
Compare
268dcec to
71b717c
Compare
|
Windows run of this head (
Upstream skips the Windows job on PRs, so this is the first Windows run of this branch. |
|
Windows test: head AI-assisted (Claude Code). |
|
Two findings on head 1. It no longer merges onto current
I resolved these locally by testing 2. The Mound (PPSA26223), 150 s each, observation only.
Palworld (PPSA23126) with the same merge (plus the three file/event export declarations from AI-assisted (Claude Code). |
|
For anyone carrying this: the merge of head
Windows 10, GCC 15.2.0 (WinLibs r7), Release: full build 0 errors, 26 of 26 tests in the socket, poll, dup, fstatfs, file system, TCP/UDP and libSceNet filter pass. No title run on this exact merge. AI-assisted (Claude Code). |
|
Interaction of this PR with the other open descriptor PRs, from
AI-assisted (Claude Code). |
|
Heads-up before review: this PR reworks the guest-socket descriptor scheme to ordinary numbers below A plain rebase therefore isn't mechanical: every Options as I see them: either this PR is a deliberate counter-proposal to the |
71b717c to
d39b707
Compare
e019fbf to
e0ec0c8
Compare
|
Rebased onto current Linux Debian 12 / GCC 12.2 Release: built the affected libraries and focused test targets (148 Ninja steps); CTest passed 10/10, including |
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
|
|
Reran ProsperoLight (PPSA99002) on this head ( (41 in one run). Tested with Claude Code assistance. |
|
Opened #4924 on top of this branch for the |
With libSceNet sockets on ordinary descriptor numbers (boykopovar#4391), a title that makes a libSceNet socket non-blocking with plain fcntl(F_GETFL) and fcntl(F_SETFL, O_NONBLOCK) reached File::Fcntl, whose classification throws for a socket. libSceNet now registers a status control with libkernel, like its option setter: F_GETFL returns O_RDWR with the socket's non-blocking flag, F_SETFL sets it through SO_NBIO, as fcntl already does for libkernel sockets. ProsperoLight (PPSA99002) stopped here on Linux. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017WeVmjnnPPKdxVTpr2Vjtw
With libSceNet sockets on ordinary descriptor numbers (boykopovar#4391), poll on a libSceNet socket threw "neither a socket nor a pipe": poll only knew libkernel sockets and pipes, while select already asks libSceNet through its poller. libSceNet now lends libkernel the host socket behind a descriptor, together with an owner that keeps it open, so poll puts it in the same WSAPoll or poll call as libkernel sockets. ProsperoLight (PPSA99002) stopped here on Linux and now reaches its PC list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvDbpwUPTa78oCAJqe7m9K
With libSceNet sockets on ordinary descriptor numbers (boykopovar#4391), a title that makes a libSceNet socket non-blocking with plain fcntl(F_GETFL) and fcntl(F_SETFL, O_NONBLOCK) reached File::Fcntl, whose classification throws for a socket. libSceNet now registers a status control with libkernel, like its option setter: F_GETFL returns O_RDWR with the socket's non-blocking flag, F_SETFL sets it through SO_NBIO, as fcntl already does for libkernel sockets. ProsperoLight (PPSA99002) stopped here on Linux. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017WeVmjnnPPKdxVTpr2Vjtw
With libSceNet sockets on ordinary descriptor numbers (boykopovar#4391), poll on a libSceNet socket threw "neither a socket nor a pipe": poll only knew libkernel sockets and pipes, while select already asks libSceNet through its poller. libSceNet now lends libkernel the host socket behind a descriptor, together with an owner that keeps it open, so poll puts it in the same WSAPoll or poll call as libkernel sockets. ProsperoLight (PPSA99002) stopped here on Linux and now reaches its PC list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvDbpwUPTa78oCAJqe7m9K
* feat(libkernel): implement sigsuspend on the pending-signal set (cherry picked from commit b3d850d) * docs(libkernel): record sigsuspend 32-signal mask limit (cherry picked from commit 38e2db3) * feat(libkernel): share pause wait loop and _sigprocmask restore in sigsuspend (cherry picked from commit 1ce5c2c) * feat(libkernel): EVFILT_VNODE on macOS through the host kqueue Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 84bb450) * feat(libkernel): implement mincore Implement mincore (+hFjyohmOU0) in libkernel following FreeBSD 11's sys_mincore (sys/vm/vm_mmap.c). Validate page alignment, return EFAULT for null vector, check range bounds and residency via sceKernelVirtualQuery, and report MINCORE_INCORE (1) for resident pages. Required by a Java 25 homebrew title. (cherry picked from commit 7781eda) * fix(libkernel): round mincore address down as FreeBSD does Follow FreeBSD 11's sys_mincore by rounding unaligned address down to page boundary rather than returning EINVAL. Update guest memory test and document unmodeled residency/referenced/modified bits in libkernel technical debt. (cherry picked from commit 3699eff) * fix(libkernel): follow kern_mincore order and report reserved pages as not resident Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit 2854d51) * feat(libc): add optional log timestamps (cherry picked from commit 2cc4999) * fix(libkernel): accept MSG_DONTWAIT in the socket send and receive calls send, sendto, sendmsg, recv, recvfrom and recvmsg failed with EOPNOTSUPP for MSG_DONTWAIT (0x80), so code that polls a blocking socket with it got an error on every call instead of its data or EWOULDBLOCK. FreeBSD 11.4 defines the flag in sys/sys/socket.h: #define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ and soreceive_generic() (sys/kern/uipc_socket.c) treats it as a non-blocking socket for that one call: if ((so->so_state & SS_NBIO) || (flags & (MSG_DONTWAIT|MSG_NBIO))) { SOCKBUF_UNLOCK(&so->so_rcv); error = EWOULDBLOCK; goto release; On Linux and macOS the flag now maps to the host's MSG_DONTWAIT, next to MSG_PEEK on a receive and MSG_NOSIGNAL on a send. Winsock has no per-call non-blocking flag, so Windows keeps failing with EOPNOTSUPP for it; TechnicalDebt records that. Other flags still fail with EOPNOTSUPP. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 7afd889) * fix(libkernel): answer fcntl status flags on libSceNet sockets With libSceNet sockets on ordinary descriptor numbers (boykopovar#4391), a title that makes a libSceNet socket non-blocking with plain fcntl(F_GETFL) and fcntl(F_SETFL, O_NONBLOCK) reached File::Fcntl, whose classification throws for a socket. libSceNet now registers a status control with libkernel, like its option setter: F_GETFL returns O_RDWR with the socket's non-blocking flag, F_SETFL sets it through SO_NBIO, as fcntl already does for libkernel sockets. A homebrew title stopped here on Linux. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017WeVmjnnPPKdxVTpr2Vjtw (cherry picked from commit 5dcf28d) * fix(libc): preserve path services through process exit (cherry picked from commit 99ae2e8) * fix(memory): preserve process-owned services during exit (cherry picked from commit d50eed2) * fix(libkernel): keep host standard streams open on guest close Guest descriptors are host C runtime descriptors. Closing descriptor 0, 1 or 2 closed the host process's standard stream, and the runtime then gave that number to the next file opened anywhere in the process, including files libkernel opens itself, such as the APR reader's. The title's next close of the same number closed that file mid-read. close and sceKernelClose now fail with EBADF for descriptors 0 to 2 that were open when libkernel loaded, and leave them open. A standard descriptor that was not open at load can still be opened and closed by the guest. A title calls sceKernelClose(0) repeatedly while loading asset bundles, which made APR reads return 0 or a part of the requested bytes and raised UCRT invalid parameter reports from close. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 8029428) * fix(libkernel): poll libSceNet sockets with the host wait With libSceNet sockets on ordinary descriptor numbers (boykopovar#4391), poll on a libSceNet socket threw "neither a socket nor a pipe": poll only knew libkernel sockets and pipes, while select already asks libSceNet through its poller. libSceNet now lends libkernel the host socket behind a descriptor, together with an owner that keeps it open, so poll puts it in the same WSAPoll or poll call as libkernel sockets. A homebrew title stopped here on Linux and now reaches its PC list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvDbpwUPTa78oCAJqe7m9K (cherry picked from commit 62d8eea) * fix(libkernel): answer F_GETFD and F_SETFD on a guest socket fcntl on a guest socket handled F_GETFL and F_SETFL only and failed every other command with EINVAL, so libcurl's fcntl(fd, F_SETFD, FD_CLOEXEC) on a new socket failed (seen in a homebrew title, boykopovar#4796). Record FD_CLOEXEC per socket descriptor: F_SETFD sets or clears it, F_GETFD reads it, SOCK_CLOEXEC sets it at creation, and dup, dup2 and close start without it, as FreeBSD's kern_fcntl and kern_dup do. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> (cherry picked from commit 84aa234) * fix(libkernel): fail sceKernelMprotect over an unmapped range with EINVAL instead of aborting The allocation tracker threw a runtime_error (a hole in the protected range) from inside sceKernelMprotect, which terminated the title. mprotect already turned the exception into EINVAL. sceKernelMprotect and sceKernelMtypeprotect now check that the range is registered first and return EINVAL; the retype of direct mappings is skipped on failure. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> (cherry picked from commit 05ffb45) * fix(libkernel): fall back below a mapping hint with no room above it A mapping without MAP_FIXED treated its address as the lowest place it could go, and a hint at or above the end of the guest arena threw on the host. FreeBSD 11.4's vm_mmap_object places such mappings with vm_map_find_min, which takes the address as a hint only: it tries at or above it, then again from its minimum address. GuestArenaAllocateFromHint does the same in the arena: at or above the hint when it lies below the arena's end and a range fits there, otherwise from the arena's start. MapPlaced and the Windows mmap_aligned use it for hinted mappings; GuestArenaAllocateAtOrAbove keeps its meaning for the callers that need a range above an address. A homebrew title reserves its JIT range with sceKernelReserveVirtualRange and a hint near its own code, a host address above the arena here, and aborted with "mapping address hint is above the guest address space arena" when launching a 3DS title. (cherry picked from commit a016b4f) * docs(debt): note the fallback of mapping hints with no room above them (cherry picked from commit aca7a3a) * fix(libkernel): check every part of an mprotect range for pins before protecting the first Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> (cherry picked from commit 238fe1e) * fix(libkernel): give an inheriting thread its creator's priority Measured on a PS5 (firmware 13.60): a thread created with PTHREAD_INHERIT_SCHED, a null attribute or a default attribute runs at its creator's priority, whatever priority the attribute holds; with explicit scheduling it takes the attribute's priority. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 143eb6a) * fix(libkernel): convert local time with the host time zone sceKernelConvertUtcToLocaltime and sceKernelConvertLocaltimeToUtc returned the time unchanged while libc localtime follows the host zone, so a title that mixes them shows UTC as local time (boykopovar#5067). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk (cherry picked from commit 56c8f34) * fix(libkernel): report west_sec as seconds east of UTC A homebrew emulator documents that the console fills west_sec with the offset east of UTC despite the field's name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk (cherry picked from commit ae7f5e3) * fix(libkernel): call tzset before reading the host zone offsets Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk (cherry picked from commit 1614d82) * fix(libkernel): report the zone's daylight saving amount from sceKernelConvertLocaltimeToUtc libc mktime subtracts it when tm_isdst is set outside summer time, so it must not be zero there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk (cherry picked from commit 15969f2) * fix(libSceSystemService): end LoadExec exit without running guest exit handlers (cherry picked from commit 2dd7f2b) * feat(libc): lazily initialize application heap on first access (cherry picked from commit cee2006) * fix(libkernel): name the failing vnode watch in the kqueue notification error The Windows error for a refused FindFirstChangeNotification was one string shared by WatchParent and WatchContents, so the log could not tell which handle or path was denied. Build it from the watcher, the path the API was given and GetLastError instead. Still throws: the EVFILT_VNODE attach path is vfs_kqfilter, which returns only EINVAL, ENOMEM or 0, with EBADF from fget before it, and consults no directory permission, so no FreeBSD errno stands for a host that refuses to notify. (cherry picked from commit e9d3677) * docs(debt): keep title IDs out of the ported libkernel debt lines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj * fix(libkernel): keep the reused-page table on Darwin after the exit-lifetime change The picked lifetime change moved the physical-used table into the process state behind a Linux-only guard. This fork's direct memory zeroes reused pages on Darwin as well, so the table and its accessor need the same guard as ZeroReusedPhysical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj * test(libc): do not register the lazy application-heap test on macOS The lazy mode needs process parameters that ApplicationHeap.cpp installs only on Windows and Linux, so on macOS the test fails deterministically. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj --------- Co-authored-by: Kurenaiiiii <Kurenaiiiii@users.noreply.github.com> Co-authored-by: Oleksandr Sierov <50950970+OleksandrS23@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Amirtheshwaran Navaneethakrishnan <anavane1@charlotte.edu> Co-authored-by: Adrià Franch <adriadam10@gmail.com> Co-authored-by: MarcZX100 <marczxrr@gmail.com> Co-authored-by: milescoviello <kitslayer29@gmail.com> Co-authored-by: Nicolas Falesy <112726756+nicolasfalesy@users.noreply.github.com> Co-authored-by: krishalivaibhav <krishalivaibhav@gmail.com> Co-authored-by: SynnZer0 <243459655+SynnZer0@users.noreply.github.com> Co-authored-by: xXPBSXx <20614131+xXPBSXx@users.noreply.github.com> Co-authored-by: Yossi Yadgar <yadgar360@gmail.com> Co-authored-by: hugodearaujo <hugoinjustice@gmail.com> Co-authored-by: David-cmrg <202826622+David-cmrg@users.noreply.github.com> Co-authored-by: hamb3r <hamb3r> Co-authored-by: Rujul Talekar <113801876+Roojool@users.noreply.github.com>
What
Fixes the socket descriptor overflow reported in #4366. Libkernel sockets, socket pairs, accepted sockets, and libSceNet sockets reserve ordinary host descriptor numbers from the shared descriptor table, keeping them within
FD_SETSIZEwhile fewer than 1024 descriptors are open. Descriptor dispatch now checks socket-table membership;selecthandles libkernel sockets alongside the existing descriptor groups. The kqueue and file-event paths also identify sockets by table membership so the low-numbered descriptors work with currentmain.Carries screamm's implementation commit
20378375bwith its original author preserved. Integration changes update thesetsockoptownership check, returnEBADFfromfstatfor a closed low-numbered socket descriptor, and route descriptor cleanup through the current equeue behavior. Socketfstatremains unsupported, as in the issue's proposed scope.Tested
Linux, Debian 12, GCC 12.2, Release, Ninja,
BUILD_TESTING=ON, configured from this rebased head on currentmainc13dc7e6b:libkernel,libSceNet,libScePosixForWebKitand the focused socket/event test executables (148 Ninja steps).guest_sce_net,guest_posix_filesystem,guest_socket_events,guest_poll,guest_select,guest_socket_pair,guest_dup,guest_kqueue,guest_socket_descriptorsandguest_fstatfs.python3 tools/check_conventions.py --base upstream/mainpassed.git diff --check upstream/main...HEADpassed.No Windows build or title run was performed on this head.
Checklist
main; no other open PR implements the same behavior