Repository navigation
fix(libkernel): clear select bits from nfds to the end of their word - #10777
Conversation
…as FreeBSD copies them out Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MarcZX10
left a comment
There was a problem hiding this comment.
The PS5 measurements and FreeBSD comparison support clearing only through the end of the final 64-bit word selected by nfds. The implementation applies this on readiness and timeout returns, preserves words beyond that boundary, and leaves error returns untouched. Tests cover nfds == 0, timeout, readiness, an excluded descriptor within the final word, and preservation of the next word. Local git diff --check and the conventions checker pass; hosted test/build jobs are skipped by the current path policy, so I could not confirm a hosted native run.
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
What
selectleaves set bits in place fromnfdsup to the end of their 64-bit word, where the console clears them.@orezraey measured this on a PS5 (firmware 13.60, payload process,
pselect.logfrom #10310):nfds_below_fd:nfds16 with descriptor 16 set and a zero timeout returns 0 with the bit cleared (bit=0).nfds_0_ready:nfds0 leaves the bit set (bit=1).FreeBSD 11.4's
kern_selectexplains both cases (sys_generic.c). It sizes the sets asncpubytes = roundup(nd, NFDBITS) / NBBYand, on success, copiesncpubytesof its output sets back to each non-null set (putbits, L1156-L1164). Those output sets hold only the ready bits. So every bit fromnfdsto the end of its 64-bit word comes back as 0, words past it are not touched, and withnfds0 nothing is copied. On an error (EINTR,EBADF,EINVAL) nothing is copied either.On main,
select_nid_postfix(Socket.cpp) clears only the descriptors it asked about, all of them belownfds, on both the ready and the timeout return. This addsClearDescriptorsFrom, which clears the bits fromnfdsto the end of that word in each non-null set, and calls it on those two returns. Error returns still leave the sets alone. It does nothing whennfdsis a multiple of 64, 0 included.Two existing tests pinned the old behaviour, and neither cites a measurement:
GuestSelect.cpprequired the bit atnfdsto survive a timeout (theselect_nid_postfix(reader, …)case). That is the measurednfds_below_fdcase, so it now requires the bit to be cleared, along with bit 63, while bit 64 in the next word is kept. New cases covernfds0 (bit kept, as measured) and the ready path (bits pastnfdscleared, the ready bit kept).GuestSelectWait.cpprequired bit 63 to surviveselectwithnfds1. It is in the same word, so it is now cleared, and a bit in the next word is required to survive.Tested
Windows 11, WinLibs GCC 15.2.0 r7, full Release build on main f26434a with this change: no failed steps.
guest_select,guest_select_wait,guest_kernel_sys_pselect,guest_socket_descriptors,guest_sce_netandguest_kernel_syspass, 3 runs of 6/6.Socket.cppand these tests,guest_selectandguest_select_waitboth fail (2 runs).tools/check_conventions.py --base origin/mainpasses.Overlap
selectdebt entry ("where AnyPS5 keeps it"). Whichever lands second should drop that sentence. I'm happy to do it here if docs(libkernel): record select limits as measured on a PS5 #10310 lands first.pr_overlaplists fix(libkernel): getsockopt reads options of libSceNet sockets #9515, feat(libSceNet): implement the Ex and Internal socket forms, sceNetSysctl, scope-ID text and the default route #9578 and fix(libkernel): poll files on standard descriptors as vnodes #10456 forSocket.cpp/GuestSelect.cpp. They conflict with main and don't touch these lines: fix(libkernel): poll files on standard descriptors as vnodes #10456 changes the descriptor loop and adds a test function beforeKqueues. My own fix(libkernel): return EINTR from pselect when its mask unblocks a pending signal #10501 (pselect) callsselectand saves and restores whole words up tonfds, so it is unaffected.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code