Repository navigation
fix(libkernel): keep host standard streams open on guest close - #3295
Conversation
|
Thank you for your interest in the project! We are sorry, but we cannot accept more PRs while we work through the existing backlog. This PR has been automatically closed and labeled "intake paused". This is not a judgment of the quality of your changes. |
|
Needs a rebase: it conflicts with main in |
|
Data point from Vampire Survivors (PPSA21703) on today's
|
Guest descriptors are host C runtime descriptors. Closing descriptor 0, 1 or 2 closed the host process's standard stream, and the runtime then gave that number to the next file opened anywhere in the process, including files libkernel opens itself, such as the APR reader's. The title's next close of the same number closed that file mid-read. close and sceKernelClose now fail with EBADF for descriptors 0 to 2 that were open when libkernel loaded, and leave them open. A standard descriptor that was not open at load can still be opened and closed by the guest. PPSA21703 calls sceKernelClose(0) repeatedly while loading asset bundles, which made APR reads return 0 or a part of the requested bytes and raised UCRT invalid parameter reports from close. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@SynnZer0 @oneandonlydean The rebase asked for above is ready on Only the conflicting lines changed;
Tested:
Besides Blasphemous 2 (#4223) and Vampire Survivors (@Nesyth's runs above), there is now a third title: @WallisSkill reports in #5892 that Cat Quest III (PPSA15065) stays on the loading screen (#4909) without that PR's commit 1, 4485d02f6. That commit is a narrower copy of this fix: it changes #5892 and @xXPBSXx's #5938 (opened today) also edit AI-assisted: written with Claude Code; I checked the conflict resolution with |
|
Pushed @nikowolf123's rebase (8029428) here; it merges cleanly with current main. |
9c30f0e to
8029428
Compare
|
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.
|
The area-labels workflow listed open PRs with -L 200, so with more than 200 open PRs the older ones never entered the todo list and never got their area labels (#3295 changes libkernel and has no libkernel label). List up to 1000; the head -n 40 cap still bounds labeler work per run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zyXkUzTZGh3nBwNMtrLaW
What
closeandsceKernelCloseno longer close descriptors 0 to 2 that were open when libkernel loaded. They fail withEBADFand leave the descriptor open.Guest descriptors are host C runtime descriptors. When a title closed descriptor 0, the host process's stdin was closed, and the C runtime then gave descriptor 0 to the next file opened anywhere in the process, including files libkernel opens itself, such as the
std::ifstreamof the APR reader (Apr.cpp_readFile). The title's next close of descriptor 0 then closed that file during the read.PPSA21703 (Vampire Survivors, Unity) calls
sceKernelClose(0)repeatedly while loading its asset bundles: 27 times in one run, every call after the first failing withEBADF(temporary logging, not part of this PR). The symptoms were different on every run:APR: read of …\vs_local_assets_character_<name>.bundle at offset 0 returned 0 of N bytes, and partial reads such as13833 of 15745;APR: read failed for …;FATAL: UCRT invalid parameterfromclose_nid_postfix, which, unlikesceKernelClose, calls_closewithout suppressing the invalid-parameter handler.When a read failed, the destination memory was committed
PAGE_READWRITEand the files were complete on disk, so this is not write-watch protection or the APR execution order. APR itself is unchanged.File/src/HostStreams.cpp(new):File::IsHostStream(fd)records at load whether 0 to 2 are open (_get_osfhandlewith the invalid-parameter handler suppressed on Windows,fcntl(F_GETFD)elsewhere). A standard descriptor that was not open at load (no console) can still be returned byopenand closed normally.sceKernelClose→SCE_KERNEL_ERROR_EBADF;close/_close→-1,errnoEBADF, for those descriptors.docs/dev/TechnicalDebt.md: the console's result for closing 0 to 2 is unknown; recorded with the title that needs it.tests/GuestHostStreams.cpp(new,guest_host_streams): for each of 0 to 2 that is open, both calls fail withEBADFand the descriptor stays usable; a new pipe does not reuse those numbers.Tested
Windows 11, MinGW-w64 GCC 15.2.0 (WinLibs 15.2.0posix-14.0.0-ucrt-r7), full build with
BUILD_TESTING=ON:ctest: 768/769 passed. The failure isguest_filesystem(CreateSymbolicLinkWwithout Developer Mode), which also fails on the base on this machine.python tools/check_conventions.py --base origin/main: passed.HostStreams.cppusesfcntlthere).Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code