Skip to content

fix(libkernel_sys): fail fpathconf on a kqueue or shm descriptor with EOPNOTSUPP - #11296

Merged
adriadam10 merged 4 commits into
boykopovar:mainfrom
tablefrogpillow:fix/fpathconf-kqueue-shm-eopnotsupp
Oct 28, 2026
Merged

adriadam10 merged 4 commits into
boykopovar:mainfrom
tablefrogpillow:fix/fpathconf-kqueue-shm-eopnotsupp

Conversation

@tablefrogpillow

@tablefrogpillow tablefrogpillow commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

What

fpathconf on a kqueue or shm_open descriptor returned the UFS constants (_PC_LINK_MAX 32767, _PC_NAME_MAX 255, _PC_PIPE_BUF 512, …) because _fpathconf_nid_postfix only treats FIFOs and sockets as descriptors without a vnode. FreeBSD 11.4 kern_fpathconf (sys/kern/kern_descrip.c:1411-1429) answers _PC_ASYNC_IO (200112) for every descriptor and then, for a descriptor with no vnode that is not a pipe or socket, returns -1 with EOPNOTSUPP. This adds that case: a kqueue (IsKqueueDescriptor) or shared-memory (File::IsSharedMemoryDescriptor_nid_no_patch) descriptor now fails with EOPNOTSUPP for every name except _PC_ASYNC_IO.

Scope. This covers the descriptors that IsSharedMemoryDescriptor_nid_no_patch recognises: kqueue, and named shm_open objects on both Linux and Windows, plus anonymous shm_open(SHM_ANON, …) on Linux. It does not fix the Windows anonymous SHM_ANON case reported in #11291: on Windows that descriptor is not registered as shared memory, so IsSharedMemoryDescriptor_nid_no_patch returns false and fpathconf still falls through to the UFS values. That is a separate shared-descriptor-recognition gap, tracked in #11372.

Tested

Linux (Ubuntu 24.04, x86_64). ctest --test-dir build -R '^guest_kernel_sys$' passes with the change and aborts without it (guest errno 22 instead of 45). Dropping only the shared-memory half of the new branch (keeping the kqueue half) makes the named-shm_open case fail at the check, so both halves of the condition are covered. The GuestKernelSys fpathconf cases use a kqueue and a named shm_open descriptor (named recognition works on both platforms, per the Windows run reported in review). Also re-verified building and passing after a local rebase onto current main (4e43321). tools/check_conventions.py --base origin/main and tools/pr_overlap.py both clean. A Windows rerun of guest_kernel_sys would still be welcome from someone with a Windows build.

Checklist

🤖 Generated with Claude Code

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Linux regression evidence is useful and the added branch is reached after the existing FIFO/socket handling. One validation gap remains: the reported issue includes Windows behavior, but the only focused run listed is Linux, and the hosted Windows product job is skipped for these paths. Could you run guest_kernel_sys on Windows at the exact head and record the kqueue and anonymous shared-memory cases? That would exercise the Windows GuestFstat and descriptor implementations that the Linux run does not cover. I have not independently built this head.

@github-actions github-actions Bot added the fix error Closes an issue (Fixes #N) label Oct 26, 2026
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

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.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 9019 core/libs/prx/libkernel_sys/Export.cpp L36
PR 11969 core/libs/prx/libkernel/File/include/SharedMemory.hpp L11-12

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.

Pull request Shared files not compared
PR 5021 core/libs/prx/libkernel/Equeue/src/FileEvent.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/prx/libkernel/Socket/src/Udp.cpp
core/libs/prx/libkernel_sys/Export.cpp
PR 6936 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 7088 core/libs/prx/libkernel/Equeue/Equeue.hpp
core/libs/prx/libkernel/Equeue/src/FileEvent.cpp
core/libs/prx/libkernel/Equeue/src/Kqueue.cpp
core/libs/prx/libkernel/Socket/src/Udp.cpp
PR 7121 core/libs/prx/libkernel/Equeue/Equeue.hpp
core/libs/prx/libkernel/Equeue/src/FileEvent.cpp
core/libs/prx/libkernel/Equeue/src/Kqueue.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 7447 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 7509 core/libs/prx/libkernel/Equeue/Equeue.hpp
PR 8605 core/libs/prx/libkernel/Socket/src/Udp.cpp
PR 9097 core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp
PR 9161 core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/prx/libkernel_sys/Export.cpp
PR 9284 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9293 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9297 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9302 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9389 core/libs/prx/libkernel_sys/Export.cpp
PR 9473 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9575 core/libs/prx/libkernel/Equeue/Equeue.hpp
core/libs/prx/libkernel/Equeue/src/Kqueue.cpp
PR 9713 core/libs/prx/libkernel/Socket/src/Udp.cpp
core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp
PR 10332 core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp
PR 10427 core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp
PR 11031 core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp
PR 11034 core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp
PR 11216 core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp

@wachi35676

Copy link
Copy Markdown
Contributor

Windows run of head ed61cad2b321, merged onto main 0f34ebb85, WinLibs GCC 15.2.0, Release. Linux (WSL, GCC 13) passes 2/2 and fails at line 555 without the change, as you describe.

On Windows the new check fails 3/3 at line 555 (errno 22), with or without the change. I printed fpathconf for each name on Windows:

  • the kqueue gives 200112 for _PC_ASYNC_IO and EOPNOTSUPP for the rest, as intended;
  • a named shm_open("/x", O_RDWR|O_CREAT) descriptor gives EOPNOTSUPP too;
  • the anonymous SHM_ANON descriptor still gives the UFS answers (_PC_LINK_MAX 32767, _PC_NAME_MAX 255, …).

The anonymous object on Windows is a %TEMP%\anyps5-shm-* file from CreateAnonymousFile, and it isn't registered anywhere. IsSharedMemoryDescriptor_nid_no_patch → IsHostSharedMemoryDescriptor only recognises descriptors in sharedDescriptorAccess under the named-object root, so on Windows the new branch isn't reached for anonymous shm. Linux works because the memfd:anyps5 shm_open link name is matched. Recording anonymous descriptors on Windows, or another way to tell them apart, would fix both the test and the behaviour.

AI-assisted: yes (Claude Code); results above were run on this machine.

@github-actions github-actions Bot added the prx label Oct 26, 2026

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Windows follow-up exposed a failing case in the new behavior: SHM_ANON descriptors still return the UFS pathconf values, because Windows backs anonymous shared memory with a temporary file that is not present in sharedDescriptorAccess; IsSharedMemoryDescriptor_nid_no_patch therefore returns false and this new branch is skipped. That leaves the stated shared-memory behavior incomplete on Windows, and the added Windows test fails for the anonymous descriptor. Please cover the Windows anonymous shared-memory descriptor too (or narrow the claimed scope and test contract if it is intentionally unsupported), add a regression assertion, and rerun guest_kernel_sys on Windows and Linux. The existing kqueue and named-shm results do not cover this path.

@tablefrogpillow

Copy link
Copy Markdown
Contributor Author

Thanks for the Windows run and the breakdown — that's exactly right.

The anonymous SHM_ANON object is recognised as shared memory only on Linux, where IsSharedMemoryDescriptor_nid_no_patch matches the memfd:anyps5 shm_open link name. On Windows the anonymous %TEMP%\anyps5-shm-* object from CreateAnonymousFile isn't registered in sharedDescriptorAccess, so IsHostSharedMemoryDescriptor doesn't recognise it and fpathconf never reaches the new branch — hence the UFS answers and the 3/3 failure. The test baked in that Linux-only assumption.

I've switched the test (52c8d67) from an anonymous descriptor to a named one, which you confirmed is recognised and returns EOPNOTSUPP on both platforms, and it's shm_unlink-ed afterwards. It still exercises the same IsSharedMemoryDescriptor_nid_no_patch half of the branch — coverage-checked on Linux: dropping only that half (keeping the kqueue half) makes the named-shm case fail at line 555, so the branch is genuinely hit, not passing vacuously.

The remaining item — anonymous descriptors not being recognised on Windows — is a gap in the shared-descriptor tracking itself (IsHostSharedMemoryDescriptor / sharedDescriptorAccess), not in fpathconf, and it affects anything that keys off descriptor recognition rather than this export specifically. That's better fixed there (recording the anonymous %TEMP% descriptors), and I didn't want to fold an unverified Windows-only change into this one-liner — I'm building and testing on Linux here. Happy to open a separate issue for it if that's useful.

AI-assisted: yes (Claude Code); the Linux build/test/coverage-check above was run on this machine.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for changing the regression to use a named shared-memory object. That is useful cross-platform coverage for the newly added shared-descriptor check, and the prior Windows report confirms that this named object returns EOPNOTSUPP.

The issue reproduction is specifically shm_open(SHM_ANON, ...), however. Your follow-up says Windows backs that anonymous object with a temporary file that is not registered in sharedDescriptorAccess, so IsSharedMemoryDescriptor_nid_no_patch still returns false and _fpathconf_nid_postfix still falls through to the UFS constants for the reported Windows case. Please either include and test recognition of the Windows anonymous descriptor on both platforms, or narrow this PR’s stated scope to kqueue plus named shared-memory objects and leave the original SHM_ANON report explicitly unresolved (for example, with a separate issue). I am not asking anyone to close this PR.

Please also refresh onto current main (35ac3402c80b152983e8aa11196835d3a16370bf); this head is 2 commits ahead and 258 behind, and both Export.cpp and GuestKernelSys.cpp changed upstream. The merge preview is clean, but the existing Linux/Windows test reports predate the latest commit and current base. Rerun guest_kernel_sys on Linux and Windows at the rebased exact head before merge.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One concrete checklist mismatch remains: this PR still says Fixes #11291, but #11291 specifically reports Windows shm_open(SHM_ANON, ...), and the author confirms the current Windows code still returns the UFS values for that descriptor. Merging this checklist would auto-close an issue whose reported Windows case remains reproducible. Please either implement and test recognition of the Windows anonymous descriptor, or remove Fixes #11291 and clearly leave that case unresolved as the earlier review requested. I also refreshed sync: current upstream/main is 204c6747d0a1cbaf932def3dea0778810cc3935e; this head is 2 ahead / 261 behind. Export.cpp and GuestKernelSys.cpp changed since the base; merge preview is clean. Rebase and rerun guest_kernel_sys on Linux and Windows at the resulting exact head.

@tablefrogpillow

Copy link
Copy Markdown
Contributor Author

You're right on both points — thanks for the careful review.

Scope / Fixes #11291. I've taken the narrowing option: Fixes #11291 is removed, and the PR now states plainly that it covers kqueue plus named shm_open (recognised on both platforms) and anonymous shm_open(SHM_ANON, …) on Linux, while the Windows SHM_ANON case in #11291 is not fixed and remains reproducible. I didn't take the "implement Windows anonymous recognition" option because it needs a Windows build to verify and I only have Linux here — I didn't want to push an unverified Windows change.

I filed #11372 for the Windows case. The mechanism there (from reading the source): the anonymous shm_open path calls CreateAnonymousFile() without recording the descriptor in sharedDescriptorAccess, and on Windows IsHostSharedMemoryDescriptor returns false for any descriptor not in that map; on Linux the same descriptor is recognised via the /memfd:anyps5 shm_open link name instead. So merging this PR no longer auto-closes an issue whose reported case still reproduces.

Rebase. Rebased onto current main (4e43321); PR head is now cfd663103a. I reran guest_kernel_sys on Linux at that exact head: it passes with the change and aborts without it (guest errno 22 instead of 45), and dropping only the shared-memory half of the branch makes the named-shm_open case fail, so both halves stay covered. check_conventions and pr_overlap are clean. I can't produce the Windows run at this head myself — that would still be welcome from someone with a Windows build.

AI-assisted: yes (Claude Code); the Linux build/test/coverage-check was run on this machine.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@tablefrogpillow
tablefrogpillow force-pushed the fix/fpathconf-kqueue-shm-eopnotsupp branch from cfd6631 to 35220d2 Compare October 26, 2026 19:17
@tablefrogpillow

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (afc780e681). The only conflict was in _fpathconf_nid_postfix: PathConfigurationValue went from two arguments back to one on main, so the kqueue/shm EOPNOTSUPP guard now sits in front of the 1-arg call. guest_kernel_sys passes at the new head (35220d20f9), and python3 tools/check_conventions.py --base origin/main is clean.

AI-assisted: yes

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@tablefrogpillow

Copy link
Copy Markdown
Contributor Author

@MarcZX10 this should be ready for another look when you have a moment — all three points from your reviews are resolved:

Also flagging that #11403 lists this one under Depends on, so a merge here unblocks that too.

AI-assisted: yes

@BunnyFl

BunnyFl commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

A Windows run of 35220d20f9 merged onto main 74acfad65b with no conflicts: Windows 11 (10.0.26200), WinLibs GCC 15.2.0 r7 (MinGW-w64 UCRT), Release, BUILD_TESTING=ON, each test run three times with ctest -V.

  • guest_kernel_sys passes in all three runs, with this PR and on main.
  • Control: with only libkernel_sys/Export.cpp put back to main's version (this PR's test kept), it fails in all three runs at the new CheckUnsupportedPathconf check (Kernel sys check failed at line 540 (guest errno 22); the test expects errno 45).

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact head 35220d20f9a4715c0e610ce30a2676e6b2397b63 after the scope/checklist and sync follow-ups. The PR now explicitly limits itself to kqueue and the shared-memory descriptors this helper recognizes, states that Windows SHM_ANON remains unresolved in #11372, and no longer claims to close #11291. The PcAsyncIo special case remains before the new descriptor rejection; the tests cover both fpathconf aliases for a kqueue and named shared memory and check EOPNOTSUPP (errno 45). The Windows runtime report at this head passes guest_kernel_sys 3/3 with a baseline-source control; the Linux report covers the focused path and its negative control. Current-main merge preview is clean; upstream changes since the branch do not edit the modified fpathconf logic or new test block. git diff --check and conventions pass. This approval is scoped to the stated partial behavior and does not claim the Windows anonymous-shm case is fixed.

@tablefrogpillow

Copy link
Copy Markdown
Contributor Author

Thanks @MarcZX10 for working through the scope and sync iterations, and @BunnyFl for the Windows run at the exact head 35220d20f9. The PR now limits itself to kqueue and the shared-memory descriptors this helper recognizes, with the Windows SHM_ANON case tracked separately in #11372 rather than claimed here.

AI-assisted: yes

@adriadam10 adriadam10 self-assigned this Oct 27, 2026
@adriadam10
adriadam10 force-pushed the fix/fpathconf-kqueue-shm-eopnotsupp branch from 35220d2 to c5f5df6 Compare October 28, 2026 07:31
@github-actions github-actions Bot added libkernel needs rebase Conflicts with main, rebase needed labels Oct 28, 2026
… EOPNOTSUPP

_fpathconf_nid_postfix only treated FIFOs and sockets as descriptors without
a vnode, so a kqueue or shm_open descriptor fell through to the UFS constants
(LINK_MAX 32767, NAME_MAX 255, PIPE_BUF 512). FreeBSD 11.4 kern_fpathconf
(kern_descrip.c:1411-1429) answers _PC_ASYNC_IO for every descriptor and
returns EOPNOTSUPP for a no-vnode descriptor that is not a pipe or socket.
Return EOPNOTSUPP for kqueue and shared-memory descriptors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tablefrogpillow and others added 3 commits October 28, 2026 08:43
An anonymous shm descriptor is recognised as shared memory only on
Linux, where the memfd link name is matched; on Windows the anonymous
%TEMP% object is not registered in the shared-descriptor table, so the
descriptor is not recognised and fpathconf never reaches the EOPNOTSUPP
branch. A named descriptor is recognised on both platforms, so the
check now opens a named object and unlinks it, keeping the same branch
coverage without a Linux-only assumption.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… can import them

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@adriadam10
adriadam10 force-pushed the fix/fpathconf-kqueue-shm-eopnotsupp branch from c5f5df6 to 149ec09 Compare October 28, 2026 07:59
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 28, 2026
@adriadam10
adriadam10 merged commit 241649e into boykopovar:main Oct 28, 2026
10 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased onto current main (the only conflict was the new kenv test block in GuestKernelSys.cpp, both kept); the _nid_no_patch rename of the kqueue check stays so libkernel_sys.prx loads on Windows. Re-checked the _PC_ASYNC_IO ordering and the kqueue and named-shm tests; merged.

milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 29, 2026
…and use the renamed kqueue check

sceKernelJitCreateSharedMemory's size object and maximum protection live
in libkernel's g_jitDescriptors, which the receive side of SCM_RIGHTS
doesn't fill, so a received JIT descriptor failed
sceKernelJitMapSharedMemory with EBADF (XairRrR's review). Passing one
now throws, with the random device and directory cases; IsJitSharedMemory
answers it. The merge of main brought boykopovar#11296's rename of
IsKqueueDescriptor to IsKqueueDescriptor_nid_no_patch, which the kqueue
check now calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants