You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sceKernelPread, sceKernelPwrite and sceKernelFtruncate abort the process on Windows instead of returning errors #2423
On Windows, sceKernelPread and sceKernelPwrite are thin wrappers over the POSIX pread_nid_postfix / pwrite_nid_disambig1_nid_postfix (core/libs/prx/libkernel/File/src/Stdio.cpp). Those throw std::runtime_error on every failure and on a null buffer. The exception can't cross the guest boundary, so the process aborts.
The Linux build's sceKernelPread/sceKernelPwrite (the #else branch) return SceErrorFromErrno(...) instead. That means the same guest call returns an error code on Linux and kills the process on Windows.
ftruncate_nid_postfix / sceKernelFtruncate throw on any host failure on both platforms.
Each case below was run in its own process against current main (Windows 11, WinLibs GCC 15.2.0 r7). Every row aborted with terminate called after throwing ... std::runtime_error:
call
Windows
expected (Linux build / FreeBSD)
sceKernelPread(9999, buf, 4, 0)
abort: pread failed, fd=9999, errno=9
0x80020009 (EBADF)
sceKernelPwrite(9999, buf, 4, 0)
abort: pwrite failed, fd=9999, errno=9
0x80020009
sceKernelPread(fd, buf, 4, -1)
abort: invalid argument
0x80020016 (EINVAL)
sceKernelPread(fd, NULL, 0, 0) (valid file)
abort: invalid argument
0
sceKernelPwrite on an O_RDONLY descriptor
abort: pwrite failed, fd=3, errno=5
0x80020009 (EBADF)
sceKernelFtruncate(9999, 0)
abort: ftruncate failed, error=9
0x80020009
sceKernelFtruncate on an O_RDONLY descriptor
abort: ftruncate failed, error=13
0x80020016 (EINVAL on FreeBSD)
The zero-length pread with a null buffer is valid and should return 0. Some engines probe a descriptor that way.
A likely fix is to give the Windows sceKernelPread/sceKernelPwrite the same early checks and SceErrorFromErrno returns as the Linux branch (NativePread/NativePwrite already exist for both platforms), and to have sceKernelFtruncate return SceErrorFromErrno instead of throwing. I haven't opened a PR for two reasons: #2170 rewrites every line of these functions (descriptor isolation), and intake is currently paused for my account. I'm happy to do it after #2170 lands, or for #2170's author to fold it in.
AI-assisted: yes (the probe was written and run with Claude Code).
Thanks @AchrafReyani for the original report, probes and suggested direction. I independently reproduced your findings on unchanged main (8b393b6e) and prepared a proposed patch with additional regression coverage.
The patch shares Linux's scalar kernel error-return paths with Windows, separates POSIX ftruncate errno handling from SCE results, and checks Windows handle access/type for the reported permission errors.
Regression
Upstream
Patched
Windows 11, WinLibs GCC 15.2 UCRT r7
17/40 passed
40/40 passed
Linux/WSL, GCC 15.2
32/38 passed
38/38 passed
These are assertion counts, not process runs. Baseline failures include the reported exceptions; the harness catches them rather than reproducing a game-process abort. Actual libc/libkernel builds and guest_file_errors, guest_filesystem, guest_file_vector passed on both platforms (3/3 each). The Linux production-source ASan+UBSan regression passed without sanitizer diagnostics.
No games, macOS, CI, full-emulator or NID-patched-runtime execution, concurrent-I/O validation, or disk-full/query/offset-restoration fault injection. Windows transfers over DWORD remain unsupported. #2029 is still open and modifies the same native helper; reconciliation is required and no combined-branch test is claimed. #2170 is closed without merging.
Sharing this as reproducible evidence for the existing issue, respecting paused PR intake; no PR opened. AI-assisted with OpenAI Codex.
I compared the proposed patch with the current #2029 head (458e7e42). It cannot be applied as-is: its NativePositioned hunk restores I/O on the shared descriptor and reintroduces the offset race that #2029 fixes. I tested a local integration that preserves ReOpenFile and separate handles, converts Windows scalar sceKernelPread/sceKernelPwrite failures to SCE error returns, and separates sceKernelFtruncate from the POSIX ftruncate_nid_postfix wrapper. Linux libkernel and the existing guest_positioned_io CTest build/pass (1/1), but Windows behavior still needs the reporter’s Windows harness and exact-head CI. Since #2029’s branch is in another contributor’s fork, I have not pushed commits into their branch. Could you and the PR author coordinate permission/ownership for integrating the compatible parts into #2029? The patch also needs a small correction: in its Windows NativeFtruncate, _chsize_s returns an errno value directly, so errno must be set from that value before mapping it.
Windows sceKernelPread/sceKernelPwrite get the Linux checks and SceErrorFromErrno returns; a zero-length transfer with a null buffer returns 0.
NativePositioned reports ERROR_ACCESS_DENIED as EBADF for reads and writes (a pread on an O_WRONLY descriptor is EBADF on FreeBSD and Linux too), other failures stay EIO. The file-pointer handling is unchanged from main, so the race fix(libkernel): isolate Windows positioned file transfers #2029 addressed is still there, as recorded in TechnicalDebt.
ftruncate returns EINVAL for a negative length and for a descriptor without write access (_chsize_s's EACCES is mapped, as @MarcZX100 noted it returns the error instead of setting errno), and passes other host errors to the guest; sceKernelFtruncate returns the kernel error.
The table's cases are checked in guest_file_vector, which also runs on Windows (guest_directory_entries is Linux-only, so checks there never reach the Windows build).
Tested: Linux full ctest, no new failures. Not run on Windows: the files cross-compile with MinGW-w64 GCC 16, and under Wine 10.0 (UCRT) WriteFile on an _O_RDONLY and ReadFile on an _O_WRONLY descriptor fail with ERROR_ACCESS_DENIED; Wine's _chsize_s differs from Windows 11 (EINVAL instead of EACCES/EBADF), so the ftruncate cases rely on your Windows measurements.
AI-assisted: yes. OpenAI Codex wrote the first draft; an AI agent (Claude Code) did most of the work: the review, the fixes, the tests and this comment.
I validated justdoston/fix/windows-file-operation-errors at 7c706c8822a0d353dacdaa615f5fd6c45effcc44 on Windows 11 using WinLibs GCC 15.2.0.
The focused guest_file_vector test passed (1/1, 0.16 s). I configured a fresh Release build, built guest_file_vector_tests and its libkernel.prx dependency, and confirmed the binaries were freshly built from this branch. The test exercises the new assertions for invalid descriptors, invalid offsets/lengths, buffer handling, permission errors, and file-content preservation.
This was a focused Windows run against the branch's pinned base, not a full-suite run or a rebase onto current main. I made no changes to the branch.
Activity
popeee99 commentedon Oct 9, 2026
Thanks @AchrafReyani for the original report, probes and suggested direction. I independently reproduced your findings on unchanged
main(8b393b6e) and prepared a proposed patch with additional regression coverage.The patch shares Linux's scalar kernel error-return paths with Windows, separates POSIX
ftruncateerrno handling from SCE results, and checks Windows handle access/type for the reported permission errors.These are assertion counts, not process runs. Baseline failures include the reported exceptions; the harness catches them rather than reproducing a game-process abort. Actual
libc/libkernelbuilds andguest_file_errors,guest_filesystem,guest_file_vectorpassed on both platforms (3/3 each). The Linux production-source ASan+UBSan regression passed without sanitizer diagnostics.Patch, reproduction commands, before/after logs and detailed limitations. Local fix commit:
8fc84d4a.No games, macOS, CI, full-emulator or NID-patched-runtime execution, concurrent-I/O validation, or disk-full/query/offset-restoration fault injection. Windows transfers over DWORD remain unsupported. #2029 is still open and modifies the same native helper; reconciliation is required and no combined-branch test is claimed. #2170 is closed without merging.
Sharing this as reproducible evidence for the existing issue, respecting paused PR intake; no PR opened. AI-assisted with OpenAI Codex.
MarcZX10 commentedon Oct 9, 2026
I compared the proposed patch with the current #2029 head (
458e7e42). It cannot be applied as-is: itsNativePositionedhunk restores I/O on the shared descriptor and reintroduces the offset race that #2029 fixes. I tested a local integration that preservesReOpenFileand separate handles, converts Windows scalarsceKernelPread/sceKernelPwritefailures to SCE error returns, and separatessceKernelFtruncatefrom the POSIXftruncate_nid_postfixwrapper. Linuxlibkerneland the existingguest_positioned_ioCTest build/pass (1/1), but Windows behavior still needs the reporter’s Windows harness and exact-head CI. Since #2029’s branch is in another contributor’s fork, I have not pushed commits into their branch. Could you and the PR author coordinate permission/ownership for integrating the compatible parts into #2029? The patch also needs a small correction: in its WindowsNativeFtruncate,_chsize_sreturns an errno value directly, soerrnomust be set from that value before mapping it.justdoston commentedon Oct 10, 2026
Since #2170 and #2029 were closed without merging, here is a version that applies to current
mainwithout touching descriptor isolation:Branch: https://github.com/justdoston/AnyPS5/tree/fix/windows-file-operation-errors
sceKernelPread/sceKernelPwriteget the Linux checks andSceErrorFromErrnoreturns; a zero-length transfer with a null buffer returns 0.NativePositionedreportsERROR_ACCESS_DENIEDasEBADFfor reads and writes (apreadon anO_WRONLYdescriptor isEBADFon FreeBSD and Linux too), other failures stayEIO. The file-pointer handling is unchanged frommain, so the race fix(libkernel): isolate Windows positioned file transfers #2029 addressed is still there, as recorded in TechnicalDebt.ftruncatereturnsEINVALfor a negative length and for a descriptor without write access (_chsize_s'sEACCESis mapped, as @MarcZX100 noted it returns the error instead of settingerrno), and passes other host errors to the guest;sceKernelFtruncatereturns the kernel error.The table's cases are checked in
guest_file_vector, which also runs on Windows (guest_directory_entriesis Linux-only, so checks there never reach the Windows build).Tested: Linux full
ctest, no new failures. Not run on Windows: the files cross-compile with MinGW-w64 GCC 16, and under Wine 10.0 (UCRT)WriteFileon an_O_RDONLYandReadFileon an_O_WRONLYdescriptor fail withERROR_ACCESS_DENIED; Wine's_chsize_sdiffers from Windows 11 (EINVALinstead ofEACCES/EBADF), so theftruncatecases rely on your Windows measurements.AI-assisted: yes. OpenAI Codex wrote the first draft; an AI agent (Claude Code) did most of the work: the review, the fixes, the tests and this comment.
sktharunbalaji13-cmd commentedon Oct 10, 2026
I validated
justdoston/fix/windows-file-operation-errorsat7c706c8822a0d353dacdaa615f5fd6c45effcc44on Windows 11 using WinLibs GCC 15.2.0.The focused
guest_file_vectortest passed (1/1, 0.16 s). I configured a fresh Release build, builtguest_file_vector_testsand itslibkernel.prxdependency, and confirmed the binaries were freshly built from this branch. The test exercises the new assertions for invalid descriptors, invalid offsets/lengths, buffer handling, permission errors, and file-content preservation.This was a focused Windows run against the branch's pinned base, not a full-suite run or a rebase onto current
main. I made no changes to the branch.fix(libkernel): return errors from file operation failures
fix(libkernel): return errors from file operation failures