Repository navigation
Description
Guest socket descriptors start at GuestSockets::FirstDescriptor = 0x10000000, so any title that puts a socket in an fd_set writes past it. Observed: Palworld (PPSA23126), The Mound (PPSA26223) and Dying Light 2 (PPSA02262) crash in the EOS SDK on FD_SET(0x10000005) (verbatim lines in their issues; see also the earlier #2170, closed for lack of a title and log, which now exist). FreeBSD 11.4 select.h:58-59 (FD_SETSIZE 1024) and kern_descrip.c:1643-1660 (descriptors are the lowest free small integers, shared between files and sockets).
Fix branch ready: screamm:fix/socket-descriptors-below-fd-setsize (20378375, one commit on main 436e310d). I cannot open it as a PR under the intake rule while #4081 is open; anyone eligible is welcome to carry it, keeping the commit as is. Unlike #2170 it leaves file numbering alone and only moves sockets into the shared table. Open PRs that still use FirstDescriptor (#4053, #4111, #3649, #4115) will need a rebase; #4053's sceKernelClose on sockets is included here.
socket,accept,socketpairandduptake the lowest free number from the table files use: on Windows that number holds a zero-accessNULhandle (the trick directory descriptors already use), on Linux a duplicate of the host socket, so anything reaching the host directly still hits the real socket. The socket table maps number to socket, so "is this a socket" is a table lookup at all 31 former range checks;FirstDescriptorand the old counter are gone.closereleases both the socket entry and the number;dup/dup2share one socket object through the host table;dup2of a file onto a socket number drops the socket entry;sceKernelClosecloses sockets.sceNetSocket/sceNetAccepttake their ids from the same table instead of counting from 32, so small libkernel numbers cannot collide with libSceNet ids.selectnow polls libkernel sockets alongside libSceNet sockets, the random device, stdio and (Linux) host descriptors in 10 ms slices (it never handled libkernel sockets before);pollthrows only for an open non-socket descriptor and reportsPOLLNVALfor a closed one. File calls that used to hitEBADFby accident on a socket now answer as FreeBSD does:lseekESPIPE,ftruncate/getdirentriesEINVAL,flockEOPNOTSUPP,fstatthrows (not implemented);preadon a closed descriptor returnsEBADFinstead of throwing.dup2of a socket onto 0 to 2 still throws, because libc writes those streams directly.- TechnicalDebt records that the numbers will not match the console's (the table also holds the runtime's own files; the first number
socket()/sceNetSocketreturn on a console and itsgetdtablesizeare unmeasured, which hugodearaujo could settle), and three paths that skip the socket table (libcfdopenon a socket, libkernelfstaton a socket, libkernelcloseon a libSceNet socket);ENOTSOCKversus the existingEBADFfor socket calls on files is unchanged. - New
guest_socket_descriptors(number below 1024,selecton a socket and a file together,closefreeing the number for a file,dupof a socket,sceKernelClose);guest_selectgains a socket-and-pipe case (Linux);guest_poll,guest_dup,guest_sce_net,guest_socket_pair,guest_fstatfs,guest_posix_filesystemupdated.
Tested on Windows 11 Pro 26220, WinLibs MinGW-w64 GCC 15.2.0 r7, Ninja, Release, BUILD_TESTING=ON, full build including libs: the 16 socket/file/poll/dup/net/http/resolver/aio/fcntl tests 3/3; ctest -j8 -E "^agc_driver_|^video_out_flip" 597/597; tools/check_conventions.py --base main and git diff --check pass. Linux: built and run in a gcc:15 container by the implementing agent, 24 related tests including guest_select 3/3. The three titles have not been run with it; their next stops still need a run.
Written with Claude Code assistance (implementation by a subagent, reviewed and validated in this session).
Activity
MarcZX10 commentedon Oct 12, 2026
Carried the socket descriptor fix as PR #4391: #4391. It reserves ordinary descriptor numbers for libkernel and libSceNet sockets and adds select/poll/dup regression coverage. The upstream implementation author is preserved. Socket fstat remains unsupported in this PR; a regression now verifies that fstat on a closed low-numbered socket descriptor returns EBADF. Linux Release focused CTests pass 6/6, and conventions/diff checks pass. No title run was performed here.
oneandonlydean commentedon Oct 13, 2026
Closing: fixed by #4391; guest sockets get ordinary descriptor numbers below
FD_SETSIZEnow. Reopen if a title still overflows itsfd_seton current main.