Repository navigation
fix(libkernel): handle fcntl and FIONREAD on a host socket descriptor - #7403
Conversation
On Linux and macOS, fcntl and ioctl threw "descriptor N is neither a file, a directory, a pipe nor a character device" for a host socket that is not a guest socket. That is what a standard descriptor is when a service manager connects it to its journal, or when a test runner starts the process with a socket as stdin; guest_kernel_fcntl's standard input check aborts then. A socket is now its own descriptor kind. Its status and close-on-exec flags go through the host as for a pipe end, FIONREAD asks the host, record locks and read-ahead hints fail with EBADF as FreeBSD's kern_fcntl fails them on a descriptor without a vnode, and O_ASYNC throws as on a pipe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
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.
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.
|
|
Also built and ran on Windows 11 (MinGW GCC 15.2) and Ubuntu 24.04 (GCC 13.3), with this PR merged onto
One small difference you may want in the debt line: AI-assisted: yes (Claude Code); results above were run on this machine. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @wachi35676 for the Windows and Linux runs, and for the datagram AI-assisted: yes (Claude Code) |
|
Independently reproduced and confirmed fixed on another Linux machine.
Before this PR, on plain
With this PR:
AI-assisted (Claude Code). |
|
Thanks @DavidAmsellem for reproducing it on AMD. The socket-as-stdin start is a clean way to show the cause. I added your runs to the description. AI-assisted: yes (Claude Code) |
|
Checked the diff against FreeBSD's |
What
On Linux and macOS,
fcntlandioctlthrew for a host socket that is not a guest socket:A standard descriptor is such a socket when a service manager connects it to its journal, or when the process starts with a socket as stdin. That makes
guest_kernel_fcntlabort in itsStandardInputFlagscase. Here the fullctest -j8run onmain1e2d9b3 failed that test 3 runs out of 3, while the test passes on its own:Started with a socket as stdin from Python's
subprocess, the same test binary aborts the same way every time; with/dev/nullas stdin it passes.A socket is now its own descriptor kind in
DescriptorControl.cpp:FIONREADasks the host.EBADF, as for a pipe. FreeBSD'skern_fcntlreturnsEBADFfor these on a descriptor without a vnode.O_ASYNCstill throws, as on a pipe.Guest sockets keep their own path, and Windows classification is unchanged. The
fcntltechnical debt entry describes the new case.Tested
Ubuntu 24.04, GCC 13.3, Release.
guest_kernel_fcntlgainsHostSocketFlags(not on Windows). It runs on a hostsocketpair:F_GETFLreportsO_RDWR;F_SETFLwithO_NONBLOCKreaches the host socket;F_SETFDandF_GETFDround-trip;FIONREADreports the 3 queued bytes;F_SETLKandF_RDAHEADfail withEBADF;O_ASYNCthrows as on a pipe.Results:
main'sDescriptorControl.cppthe test aborts withfcntl: descriptor 5 is neither a file, a directory, a pipe nor a character device. With this PR it passes 3 of 3.After rebasing onto
main4566cc3: the 419guest_*tests pass. Before that rebase, the full suite passed 1437 of 1437 underctest -j8, includingguest_kernel_fcntl.Windows 11 (MinGW GCC 15.2) and Ubuntu 24.04 (GCC 13.3), this PR merged onto
main9f25d0b (run by @wachi35676). On Windows it builds and the socket and fcntl tests pass 38/38; the change and its test are for Linux and macOS only. On Linux,HostSocketFlagsaborts withmain'sDescriptorControl.cppand passes with this PR.guest_kernel_fcntl_testsstarted with a socketpair as stdin aborts onmainand exits 0 with this PR.From the same run: for a datagram socket, Linux's
FIONREADcounts only the next datagram, and FreeBSD'ssoo_ioctlcounts every buffered byte. The fcntl entry indocs/dev/debt/libkernel.mdnow says so (91a9e56). The code still passes the host's count through.tools/check_conventions.py --base upstream/mainpasses.fix(libkernel): support socket fcntl duplication #7437 (guest sockets,
F_DUPFDandF_DUP2FDon the libSceNet path) rewrites the samefcntlline indocs/dev/debt/libkernel.md. The code doesn't overlap: this PR only changesDescriptorControl.cppfor host sockets. Whichever PR lands second needs that sentence merged, and I'll rebase this one if it's second.@DavidAmsellem reproduced it and confirmed the fix on Linux Mint 22.3, AMD RX 7900 XT (RADV, Mesa 25.2.8). On plain
main,guest_kernel_fcntlfails underctest -j8in 4 of 4 runs with the reported message, and starting the test with a socket-pair end as stdin aborts every time. With this PR (91a9e56 on 0bc3003), that start passes 3 of 3 and fullctest -j8passes 1478 of 1480. The two failures happen onmaintoo.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