Skip to content

fix(libkernel): keep the native open error when the Windows directory probe finds no directory - #8798

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
JJenkx:windows/open-keep-native-error
Oct 21, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
JJenkx:windows/open-keep-native-error

Conversation

@JJenkx

@JJenkx JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

What

On main 57fdffd, guest_filesystem aborts on Windows 11 22621 (MinGW-w64 GCC 15.2 UCRT) at the check #8640 added:

Require(sceKernelOpen(statLoop.generic_string().c_str(), 0, 0) == static_cast<int>(0x8002003eu));

sceKernelOpen on the self-referencing link returns 0x80020002 (ENOENT). Probing the call in gdb: WindowsOpenError_nid_no_patch returns ELOOP for the native open, as #8640 intended, so the error is lost afterwards. In OpenNative, an open that fails with anything but ENOENT is followed by std::filesystem::is_directory(directory, error) to handle directory opens. With the MinGW runtime that probe can set errno to ENOENT, and OpenNative then reports the probe's ENOENT (through NotFoundError_nid_no_patch) instead of the open's error. #8640 was tested on Windows 11 26200, where the probe apparently leaves errno alone; the Windows CI job does not run for these pull requests.

OpenNative now keeps the open's error and restores it when the path is not a directory. The directory branch (EEXIST, EISDIR, directory descriptor) is unchanged. This affects every error other than ENOENT that the native open returns on Windows, not only ELOOP.

#8655 (open, ELOOP below a symlink loop) changes the lines right after this block and does not conflict; this change does not depend on it.

Tested

Windows 11 22621, AMD Radeon RX 6700 XT (driver 26.8.1), WinLibs GCC 15.2 UCRT r7, Release, BUILD_TESTING=ON, fresh build directory on main 57fdffd.

  • Without the change: guest_filesystem aborts (0xc0000409) at line 957; gdb on the failing open: WindowsOpenError_nid_no_patch -> 114 (UCRT ELOOP), sceKernelOpen -> 0x80020002.
  • With the change: guest_filesystem passes; ctest -R 'file|path|stream|open|stat|dir|fopen|libc|errno|symlink|link|filesystem' 127/127.
  • Full ctest -j 32: 1799 of 1801 pass. The other two fail the same way without this change: agc_driver_image_array_window_past_layer_limit (does not build on MinGW, test(agc): align the array window test's texels at run time #8310) and agc_driver_tessellation.
  • tools/check_conventions.py passes.

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: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

🤖 Generated with Claude Code

… probe finds no directory

When the native open failed with an error other than ENOENT, OpenNative
probed whether the path is a directory with std::filesystem::is_directory.
With the MinGW runtime that probe can set errno to ENOENT, and OpenNative
then reported the probe's ENOENT instead of the open error. On Windows 11
22621 a symbolic link loop failed with ELOOP from the native open and
sceKernelOpen returned 0x80020002, so guest_filesystem aborted at the
ELOOP check added by boykopovar#8640.

Keep the open error and restore it when the path is not a directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@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.

Reviewed the exact head and its interaction with #8655. The directory metadata probe uses the error_code overload, but the C runtime may still alter errno; saving NativeOpen's failure before the probe and restoring it only when the path is not a directory preserves that original error. The directory-open branches still assign their established EEXIST/EISDIR behavior or return the directory descriptor. #8655's subsequent loop classification remains compatible when the restored native error is ELOOP. The reported Windows negative control and focused filesystem test set exercise the regression. Hosted eligibility, conventions, intake, labels, and report checks pass; platform build jobs are skipped, so I rely on the reported Windows run. No blocking issue found.

@github-actions

Copy link
Copy Markdown

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/File/src/Open.cpp
PR 6936 core/libs/prx/libkernel/File/src/Open.cpp
PR 7121 core/libs/prx/libkernel/File/src/Open.cpp
PR 7201 core/libs/prx/libkernel/File/src/Open.cpp
PR 7530 core/libs/prx/libkernel/File/src/Open.cpp
PR 8520 core/libs/prx/libkernel/File/src/Open.cpp
PR 8658 core/libs/prx/libkernel/File/src/Open.cpp

@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Manual overlap check for the files the bot could not compare: of #5021, #6936, #7121, #7201, #7530, #8520 and #8658, only #8520 touches OpenNative's directory handling, and it adds a separate branch at the start of the function (archived/app directories); none changes the post-NativeOpen probe this PR edits. #8655 inserts its loop check right after this block, as noted in the description; the two compose.

@oneandonlydean
oneandonlydean merged commit 557682c into boykopovar:main Oct 21, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants