Skip to content

feat(libkernel): report RLIMIT_NOFILE through getrlimit - #5187

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
p3n1cillin:claude/getrlimit-nofile
Oct 14, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
p3n1cillin:claude/getrlimit-nofile

Conversation

@p3n1cillin

@p3n1cillin p3n1cillin commented Oct 13, 2026 •

Copy link
Copy Markdown

What

XPSemu (PPSA97358, catalog release) loads on current main once #4377 (pthread_atfork), #4105 (execve) and #5061 (getdtablesize) are in (mlockall and the posix_spawn family are merged). It then stops at once:

terminate called after throwing an instance of 'std::runtime_error'
  what():  getrlimit: unsupported resource 8

Resource 8 is RLIMIT_NOFILE. The two call sites (guest 0xF5011B and 0xD21A78) are QEMU's os_setup_limits: getrlimit(RLIMIT_NOFILE) warns "unable to query NOFILE limit" on failure, returns if the soft limit equals the hard limit, and otherwise raises the soft limit with setrlimit and warns "unable to set NOFILE limit" on failure.

getrlimit(RLIMIT_NOFILE) now reports, as both limits, the descriptor count after which AnyPS5 itself fails with EMFILE:

  • Windows: 8192, the C runtime's limit on low-level descriptors (_setmaxstdio). Guest files and pipes are C runtime descriptors, and guest socket numbers take one too (_open_osfhandle of a NUL placeholder in Udp.cpp), so they all share that table.
  • Linux: the host's RLIMIT_NOFILE, whose soft limit libkernel already raises to the hard limit at load (OpenFileLimit.cpp).

Since both limits are equal, setrlimit with the same values succeeds as before and QEMU never needs to raise them. This mirrors the existing RLIMIT_DATA, which reports the host's limit. The console's own limit is unknown; the getrlimit debt entry is updated. Once this is in, #5061's getdtablesize could report the same value (FreeBSD returns the smaller of the soft limit and maxfilesperproc); I have kept that separate.

Tested

Checklist

🤖 Generated with Claude Code

@p3n1cillin

Copy link
Copy Markdown
Author

Linux run: Ubuntu in WSL2, GCC 15.2.0, Ninja Release, BUILD_TESTING=ON, full build of a local test head 838d4fd85. That head is main 3faa9cb40 with this PR, my other open libkernel PRs (#5013, #5061, #5078, #5098, #5183–#5187, #5191) and the open PRs the catalog titles need (#4377, #4379, #4374, #4383, #3798, #4467, #4863, #4105). All 123 libkernel and 69 libc tests pass, including guest_system_configuration, guest_getrlimit, guest_kernel_fcntl, guest_freebsd_clocks, guest_kernel_sys and guest_filesystem. Not built alone on Linux; no title run on Linux.

@babyhuey

Copy link
Copy Markdown
Contributor

A title that stops here: XPSemu (PPSA97358). On main 18c438b with #5061 merged and relinked with #4593's --linux-fixed-base 0x400000 (Linux, headless), it throws getrlimit: unsupported resource 8. With this PR stacked as well, it gets past that and xemu starts: it loads its BIOS files and builds shaders, then stops at a GPU check in its own probe (details in #5061). The stack conflicts only in GuestGetrlimit.cpp, which #5061 also edits.

@pipe1os

pipe1os commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Built and ran this on Windows: head a915c0723 merged onto main 107190d11, Windows 11, WinLibs GCC 15.2.0, Ninja Release. The merge conflicts only in docs/dev/debt/libkernel.md: main added the machdep.tsc_freq entry right above the getrlimit one, so it needs a rebase.

One thing for Linux, which I can't run here: right after getrlimit, HotSpot calls setrlimit(RLIMIT_NOFILE) with rlim_cur = MIN(0x100000, rlim_max) (os_bsd.cpp L2130-L2132), and the Java 25 eboot does the same: getrlimit(8) at 0x9EE0FE, then cmp rax, 0x100000 / cmovl on rlim_max before setrlimit at 0x9EE163. On Windows that asks for 8192/8192 and setrlimit accepts it. On a Linux host whose hard limit is above 0x100000 or unlimited, it asks for a soft limit below the hard one, and setrlimit throws, since it only accepts the values getrlimit returns (Process.cpp L333-L334), so HotSpot's retry with MAX(OPEN_MAX, original) at 0x9EE187 never runs. XPSemu's path, QEMU's os_setup_limits, never gets there because it returns when both limits are equal, and hosts with the usual 1048576 or 524288 hard limit are fine. Probably a follow-up rather than something for this PR.

XPSemu (PPSA97358) queries RLIMIT_NOFILE at start-up in QEMU's
os_setup_limits and stopped on the unsupported resource. It reports the
descriptor count after which AnyPS5 fails with EMFILE: the C runtime's
8192 low-level descriptors on Windows and the host limit on Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@p3n1cillin
p3n1cillin force-pushed the claude/getrlimit-nofile branch from a915c07 to 1aaec97 Compare October 14, 2026 07:19
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@p3n1cillin

Copy link
Copy Markdown
Author

Rebased onto main 78f1aea70 (head 1aaec9728), thanks @pipe1os. The conflicts were only adjacent additions: machdep.tsc_freq in docs/dev/debt/libkernel.md, and getdtablesize in GuestGetrlimit.cpp. I kept both sides. On Windows (MinGW GCC 15, Release) all 129 libkernel tests pass, including guest_getrlimit with both checks, and the conventions check passes.

@adriadam10 adriadam10 self-assigned this Oct 14, 2026
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked on the PR merged onto main: build + ctest green (166/166, guest_getrlimit passes), and the new test fails with the Process.cpp change reverted. The Windows branch (8192 descriptors, EMFILE test) is confirmed by @pipe1os and the author on Windows; the full Build's Windows job covers it before merge. Merging.

@adriadam10
adriadam10 merged commit 9a3e2ac into boykopovar:main Oct 14, 2026
8 checks passed
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