Skip to content

fix(libkernel): answer fcntl status flags on libSceNet sockets - #4924

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
nicolasfalesy:fix/libkernel-fcntl-scenet-sockets
Oct 14, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
nicolasfalesy:fix/libkernel-fcntl-scenet-sockets

Conversation

@nicolasfalesy

Copy link
Copy Markdown
Contributor

What

Follow-up to #4391. With libSceNet sockets on ordinary descriptor numbers, a title that makes a libSceNet socket non-blocking the POSIX way, fcntl(fd, F_GETFL) then fcntl(fd, F_SETFL, flags | O_NONBLOCK), reaches File::Fcntl, whose classification throws for a socket:

what():  fcntl: descriptor 47 is neither a file, a directory, a pipe nor a character device

libSceNet now registers a status control with libkernel, the same way it registers its option setter (KernelSetSocketStatusControl_nid_no_patch). fcntl asks it before falling back to File::Fcntl, and for a libSceNet socket it behaves as fcntl already does for libkernel sockets: F_GETFL returns O_RDWR plus O_NONBLOCK when set, F_SETFL applies O_NONBLOCK through SO_NBIO (so sceNetGetsockopt sees the same state), flags outside the status mask fail with EOPNOTSUPP and other commands with EINVAL.

This branch contains #4391's commits; the change here is the last commit (1836f8e). It only makes sense on top of #4391: on main, libSceNet numbers can collide with host descriptors.

Tested

Linux (Arch, GCC 16.2.1, Release), on #4391's head e0ec0c8 plus this commit:

  • New CheckKernelStatusFlags in guest_sce_net: get, set and clear O_NONBLOCK with fcntl on a libSceNet socket, checked against SO_NBIO, plus the EOPNOTSUPP and EINVAL cases. Passes 5/5. Without the libSceNet change it aborts with the fcntl: descriptor 7 is neither a file ... error above.
  • guest_sce_net, guest_socket_descriptors, guest_poll, guest_select, guest_dup, guest_socket_pair: all pass.
  • ProsperoLight (PPSA99002, catalog release, --to-intel), 3 runs of 60 s: no longer stops on fcntl; its next stop is poll: descriptor 47 is neither a socket nor a pipe, i.e. poll not yet knowing libSceNet sockets. That is a separate change and not part of this PR.
  • tools/check_conventions.py --base upstream/main passes.
  • Not tested on Windows.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: fix(libkernel): give guest sockets ordinary descriptor numbers below FD_SETSIZE #4391
  • Unblocks: none yet (PPSA99002 needs poll next)
  • AI-assisted: yes

EagleBearerYS added a commit to EagleBearerYS/AnyPS5 that referenced this pull request Oct 13, 2026
…lTimeouts

boykopovar#4924 adds a test after CheckKernelTimeouts and its call after CheckKernelTimeouts(), so placing the new check there made the two pull requests conflict.
@VitzS7

VitzS7 commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Heads-up from #4910, which also touches Equeue.cpp L596-605: once your lookup lands, a libSceNet socket reaches GuestSockets::Kind there as a descriptor that is not in the libkernel socket table, so a kevent read or write event on it would answer EINVAL instead of registering a knote. I noted on that PR that the native lookup you register is the natural source for the kind, and that I will rebase on whichever of the two lands first and ask it there rather than deriving the kind from the host descriptor alone. Nothing for you to change here.

@xXPBSXx

xXPBSXx commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Windows test of this PR.

Environment: Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, BUILD_TESTING=ON, -j2, libusb-cmake from a local checkout. Built from main c2565f014 with this PR and ten other open PRs (#4972, #4967, #4966, #4945, #4938, #4936, #4933, #4898, #4896, #4888) merged together; the merges had no conflict.

Result: guest_dup and guest_fstatfs (2 of 2; the branch is contained in #4933) pass.

Not checked: whether the test fails without the change in the library code; the PR was not tested alone, only in the combined merge; no title run; Linux not tested.

AI-assisted (Claude Code).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@YossiYad

YossiYad commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Linux title run with ProsperoLight (PPSA99002, catalog release): Bazzite 44, GCC 16.2, Release, RX 7700 XT (RADV), head 1836f8e93 merged into main 315260903.

  • main alone: ProsperoLight aborts during start-up with fcntl: descriptor 48 is neither a file, a directory, a pipe nor a character device, the stop this PR describes.
  • With this PR the fcntl stop is gone. The title gets through its UI start-up (EGL surface, GL programs, pad and audio) and then stops on the same socket in poll: poll: descriptor 48 is neither a socket nor a pipe. That is the stop fix(libkernel): poll libSceNet sockets with the host wait #4933 handles. With fix(libkernel): poll libSceNet sockets with the host wait #4933, which carries this commit, on main f74ec639c, ProsperoLight ran the full 60 s without a stop.
  • guest_sce_net passes 3 of 3 (--repeat until-fail:3) on the merged tree.

Merging into current main conflicts only in core/libs/tests/GuestSceNet.cpp: main added CheckSocketError(); on the line where this PR adds CheckKernelStatusFlags();. Keeping both calls builds, and that's the tree the runs above used.

With libSceNet sockets on ordinary descriptor numbers (#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
@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased onto current main (#4391 is merged, so only the fcntl commit remains; one adjacency conflict in GuestSceNet.cpp's main() kept both calls). Checked: build and ctest for libSceNet/libkernel green, guest_sce_net fails without the change, flag values match FreeBSD (O_NONBLOCK 4, EOPNOTSUPP 45, EINVAL 22). Merging once the full build is green; thanks also to @YossiYad and @xXPBSXx for the runs.

@adriadam10
adriadam10 force-pushed the fix/libkernel-fcntl-scenet-sockets branch from 1836f8e to 5dcf28d Compare October 14, 2026 17:23
@adriadam10
adriadam10 merged commit e442f4c into boykopovar:main Oct 14, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build docs libkernel needs rebase Conflicts with main, rebase needed prx

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants