WIP: fix(linux): warn about low physical RAM even with ample swap #54

Draft
mooki wants to merge 4 commits from mooki/Longshot:fix/linux-low-ram-warning into main
First-time contributor

Why

Linux players with little physical RAM received no warning when their swap space took RAM plus swap above 10 GiB. This restores the advisory warning; it does not reduce allocations or fix the reported Water Temple freeze.

What changed

  • host: memory_notice_text() in host/hos_main.c warns below the existing 10-GiB floor in physical RAM on Linux even with ample swap. Keep exact RAM/swap figures in the log, explain paging and the 16-GB recommendation, and let startup continue.
  • host: memory_notice() reuses the existing startup notice. Windowless starts log it without opening a dialog. Windows keeps its existing RAM-plus-page-file policy.
  • tests/docs: tests/test_low_memory_notice.py, README.md, CONTRIBUTING.md and docs/tested-configurations.md preserve the deterministic Linux/Windows-policy fixture and measured memory guidance; correct its README link after the upstream filename rename. Allocations, budgets, OOM policy, saves and scheduling are unchanged.

Flags and settings

No new player-facing runtime switch, menu row or ini key is introduced. These test controls and existing HOS names appear in the patch; the internal constant and fixture define are not environment settings.

Flag What it does Default now Recommendation Helps on Doesn't help on Untested on
--source in tests/test_low_memory_notice.py New test CLI option: Selects the hos_main.c whose real warning is extracted, enabling the main negative control This checkout's host/hos_main.c Off by default: an explicit test-source choice Deterministic main/PR tests Does not change a running game or its RAM Other operating systems beyond the recorded Linux/Windows-policy checks
--cc in that test Existing selector; the suite now supplies its default compiler: Chooses the C fixture compiler; the suite uses its {cxx} tool selection gcc when invoked directly; selected compiler in the suite Off by default: test tool selection GCC/Clang policy and portability checks Does not change runtime memory policy Other compilers
-DTEST_WINDOWS_POLICY New private fixture compile define, not a game build flag: Selects the unchanged Windows warning policy after the Linux host headers Second fixture variant on Linux only Off by default: a test-only mode Windows-policy assertions executed on Linux Is not native Windows execution Full Windows gameplay is not covered by it
HOS_HEADLESS Existing runtime switch, unchanged; expanded test coverage: Suppresses the startup dialog, not the LOW MEMORY log Off unless set; 1 in these windowless runs Off by default: keep the normal visible-game default Controller-free/windowless startup checks Does not disable the warning or prevent swapping Visible dialog on real small-RAM hardware
HOS_MEMORY_NEEDED_MB Existing internal constant reused for Linux's physical-RAM floor; not an environment variable: 10,240-MiB warning threshold: physical RAM on Linux, existing RAM-plus-swap policy on Windows 10240, no user setting On by default: keep the advisory warning automatic Linux starts below the physical-RAM floor despite ample swap Does not promise that 10 GiB is enough or change allocation limits Real 8-GB PCs and Windows gameplay

Measurements

main: d4a69456c9 (2026-11-12)
this PR: fix/linux-low-ram-warning @ bf0802e7d1
Hardware: RTX 4090 24 GB, NVIDIA 615.78.08, Core i9-13900K, 96,233 MiB physical RAM, Arch Linux 7.2.15-1-omarchy
Scene: startup/opening sky-and-moon movie, no loaded save; windowless, output requested 1280×720 and captures 1280×720 (startup renderer reports 1920×1080), frame generation off, render-scale override 100%, precompile and prediction off
Method: a warm-up on each release-profile build, then 15-second before/after/before/after starts. Real process-local memory cap 7,639 MiB, swap forbidden, verified before execution. The same private, unshipped memory-query test double reports 7,639 MiB RAM / 32,767 MiB swap to the executable's startup notice on both builds; driver queries remain real. A memory cap alone does not change Linux's physical-memory query. Warning presence is the measurement, not frame time or memory savings.
How to reproduce: from this PR run python -I -B tests/test_low_memory_notice.py --cc gcc (then --cc clang); for the negative control pass --source ../main/host/hos_main.c, where ../main is a checkout of the named main. The fixture executes the production warning for 7,639 MiB RAM plus 32,767 MiB swap, with visible/headless spies, boundaries and query failure. For a real low-RAM Linux start, RAM below 10 GiB with RAM plus swap above 10 GiB reproduces the missing main warning. On a large-RAM PC the recorded windowless experiment additionally needs an unshipped executable-only sysinfo fixture returning those exact counts: a cgroup cap alone cannot reproduce that query. Use a fresh copied profile, the settings above, a verified 7,639-MiB/no-swap process scope and a 15-second wall stop; read the startup line before any lengthy load. The private query fixture is not a supported player switch.

Current branch: fix/linux-low-ram-warning @ 15813ff4a5ee775e5925bee278ba74aa5ec9d2f5, rebased onto main d725b3631982ed0035ea3ac9cbe1677e9fad260c. The previously published ba1284a1 added only documentation after measured runtime bf0802e7; the rebase preserves that runtime and fixture byte for byte. The newer main differs from measured d4a69456 only in scripts, docs and tests, with no game code, so the recorded game measurements still hold and no game run was repeated.

main @ d4a69456 this PR @ bf0802e7
Low-physical-RAM warning lines, run 1 / run 2 0 / 0 1 / 1
Median warning lines per start 0 1
Run order Build Warning lines Game exit
before-1 main @ d4a69456 0 124
after-1 this PR @ bf0802e7 1 124
before-2 main @ d4a69456 0 124
after-2 this PR @ bf0802e7 1 124

Exit 124 is the deliberately bounded startup ending at its wall limit. Both warm-ups and all four measured starts have zero fatal, guest-crash, device-loss and kernel-fault counts with complete journal coverage. These were ordinary shared runs, not speed measurements.

before-1:
lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"}
[hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game
lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply
[hos host] boot: 7639 MB of memory, 32767 MB of swap
warning lines: 0
after-1:
lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"}
[hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game
lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply
[hos host] boot: LOW MEMORY: 7639 MB of memory, 32767 MB of swap; below 10240 MB of physical RAM: heavy swapping can make the game and desktop unresponsive (16 GB RAM or more recommended)
warning lines: 1
before-2:
lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"}
[hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game
lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply
[hos host] boot: 7639 MB of memory, 32767 MB of swap
warning lines: 0
after-2:
lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"}
[hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game
lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply
[hos host] boot: LOW MEMORY: 7639 MB of memory, 32767 MB of swap; below 10240 MB of physical RAM: heavy swapping can make the game and desktop unresponsive (16 GB RAM or more recommended)
warning lines: 1
base: 507 passed, 2 failed, 20 skipped in 504 s (linux, 6 at once)
branch: 508 passed, 1 failed, 20 skipped in 175 s (linux, 6 at once)

In the retained pre-rebase suite, the branch failures were tests/test_updater_asset_digest.py. The shared measured-base suite also failed tests/test_updater_asset_digest.py with the same local .NET NU1100 missing reference pack, and tests/test_appimage_package_retry.py in two timing-dependent fake-command cases under heavy load. That base AppImage test passed all nine cases in the separately requested isolated follow-up; the original full-suite failure remains reported. That d4a69456 base suite was run once for the moved pull requests and remains historical evidence, including its AppImage failure and isolated follow-up. The rebased source-check comparison follows below; no configured Forgejo runner replaces the local whole suite.

error NU1100: Unable to resolve 'Microsoft.AspNetCore.App.Ref (= 10.0.13)' for 'net10.0'.
Base AppImage suite: FAILED (failures=2)
Base AppImage isolated follow-up: Ran 9 tests in 15.166s; OK
Before (new warning fixture against main, GCC and Clang):
FAIL: wrong warning decision (swap must not hide low RAM on Linux)
After (GCC and Clang, Linux and Windows-policy-on-Linux):
PASS: production low-memory decisions, exact counts, message, headless and boot wiring

Windows-target fixture syntax passed; the Windows-policy execution on Linux is not Windows execution. The earlier Hookshot fork checks passed on Windows after the documented test-only wording repair; that is historical evidence, not a new Longshot Windows run.

Rebased whole-suite comparison

The whole suite was run after rebase on exact head 15813ff4a5ee775e5925bee278ba74aa5ec9d2f5, including all documentation rows, with the repository's default compiler and a fresh test home. Main's d725b363 suite is shared once across the moved pull requests. The missing local ASP.NET reference pack is the inherited tests/test_updater_asset_digest.py failure (NU1100); no new failure is attributed to this warning.

main @ d725b363 this PR @ 15813ff4
Complete game-free suite on the rebased sources 510 passed, 1 failed, 20 skipped 510 passed, 1 failed, 20 skipped
main @ d725b363: 510 passed, 1 failed, 20 skipped in 234 s (linux, 6 at once)
this PR @ 15813ff4: 510 passed, 1 failed, 20 skipped in 241 s (linux, 6 at once)

Not tested

Not tested: The visible dialog, real 8-GB hardware, Windows gameplay/full host build, AMD/Intel, long play and the reporter's failed session. No new hardware test request was posted. This warning cannot prevent a swap storm; absence of a warning does not guarantee sufficient memory. The historical Hookshot pressure runs still stalled, and their Water Temple load failure is not claimed fixed.

Tested but not measured: the inspected opening movie continues on both builds; no frame-rate or overhead conclusion was taken from these shared starts. Historical pressure runs still stalled, as described above.

Screenshots

Nothing on screen is changed by these windowless starts; the visible warning dialog was not captured. Nothing changes on screen in these windowless starts: the warning is in the log. The dialog itself was not captured.

main @ d4a69456 (left); this PR @ bf0802e7 (right).

New Longshot before/after startup at the same movie frame. Both continue to the opening sky and moon; the warning difference is proved by the log, not a visible dialog.

Historical context, not a matched comparison: main @ 51da0464 and this PR @ c5708cb0 (the original Hookshot warning patch).

Historical Hookshot evidence from 2026-11-12, main 51da0464 and the original warning patch: roomy Water Temple control, last capture before the pressure-stalled load, and warning-build loading screen. Different states, not a matched before/after or new Longshot result.

Risk and rollback

The advisory notice can be too cautious for a particular small scene, and a failed memory query must not invent a warning. It does not bound allocation, stop a swap storm or diagnose the Water Temple failure; the game continues after warning. Windows must retain its old RAM-plus-page-file decision. There is no new opt-out flag: reverting the Linux warning change and its guidance is sufficient; HOS_HEADLESS hides only the dialog, not the warning or memory pressure.

Reviewer notes

Start with memory_notice_text() and memory_notice() in host/hos_main.c, then the nine RAM/swap cases, query-failure checks and visible/headless spies in tests/test_low_memory_notice.py. Verify Linux physical RAM versus the unchanged Windows policy and its different continuation text. The older pressure experiment and current warning proof are deliberately separate; allocator changes, OOM policy and the reporter's freeze diagnosis are not part of this PR.

Issues

See https://github.com/NotRexed/Hookshot/issues/2838 and https://github.com/NotRexed/Hookshot/issues/1241. The warning does not close the freeze report. Original pull request: https://github.com/NotRexed/Hookshot/issues/2901. No matching issue was present in the checked Longshot issue inventory; these are historical GitHub numbers, not Forgejo issue numbers.

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Not tested.
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Flags noted, and the switch reference updated (docs/development.md, the README). — Test controls are documented in the fixture; existing headless semantics are unchanged, and README memory guidance is updated.
  • A row in docs/tested-configurations.md for each measured run.
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Docs updated.

Moved from NotRexed/Hookshot#2901.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra [email protected]

## Why Linux players with little physical RAM received no warning when their swap space took RAM plus swap above 10 GiB. This restores the advisory warning; it does not reduce allocations or fix the reported Water Temple freeze. ## What changed - host: `memory_notice_text()` in `host/hos_main.c` warns below the existing 10-GiB floor in physical RAM on Linux even with ample swap. Keep exact RAM/swap figures in the log, explain paging and the 16-GB recommendation, and let startup continue. - host: `memory_notice()` reuses the existing startup notice. Windowless starts log it without opening a dialog. Windows keeps its existing RAM-plus-page-file policy. - tests/docs: `tests/test_low_memory_notice.py`, `README.md`, `CONTRIBUTING.md` and `docs/tested-configurations.md` preserve the deterministic Linux/Windows-policy fixture and measured memory guidance; correct its README link after the upstream filename rename. Allocations, budgets, OOM policy, saves and scheduling are unchanged. ## Flags and settings No new player-facing runtime switch, menu row or ini key is introduced. These test controls and existing HOS names appear in the patch; the internal constant and fixture define are not environment settings. | Flag | What it does | Default now | Recommendation | Helps on | Doesn't help on | Untested on | |---|---|---|---|---|---|---| | `--source` in `tests/test_low_memory_notice.py` | New test CLI option: Selects the `hos_main.c` whose real warning is extracted, enabling the main negative control | This checkout's `host/hos_main.c` | Off by default: an explicit test-source choice | Deterministic main/PR tests | Does not change a running game or its RAM | Other operating systems beyond the recorded Linux/Windows-policy checks | | `--cc` in that test | Existing selector; the suite now supplies its default compiler: Chooses the C fixture compiler; the suite uses its `{cxx}` tool selection | `gcc` when invoked directly; selected compiler in the suite | Off by default: test tool selection | GCC/Clang policy and portability checks | Does not change runtime memory policy | Other compilers | | `-DTEST_WINDOWS_POLICY` | New private fixture compile define, not a game build flag: Selects the unchanged Windows warning policy after the Linux host headers | Second fixture variant on Linux only | Off by default: a test-only mode | Windows-policy assertions executed on Linux | Is not native Windows execution | Full Windows gameplay is not covered by it | | `HOS_HEADLESS` | Existing runtime switch, unchanged; expanded test coverage: Suppresses the startup dialog, not the LOW MEMORY log | Off unless set; 1 in these windowless runs | Off by default: keep the normal visible-game default | Controller-free/windowless startup checks | Does not disable the warning or prevent swapping | Visible dialog on real small-RAM hardware | | `HOS_MEMORY_NEEDED_MB` | Existing internal constant reused for Linux's physical-RAM floor; not an environment variable: 10,240-MiB warning threshold: physical RAM on Linux, existing RAM-plus-swap policy on Windows | 10240, no user setting | On by default: keep the advisory warning automatic | Linux starts below the physical-RAM floor despite ample swap | Does not promise that 10 GiB is enough or change allocation limits | Real 8-GB PCs and Windows gameplay | ## Measurements main: d4a69456c9de5131589af1fcf9a09adba4c403d1 (2026-11-12) this PR: fix/linux-low-ram-warning @ bf0802e7d10b841cef93418b0ef610a130da1993 Hardware: RTX 4090 24 GB, NVIDIA 615.78.08, Core i9-13900K, 96,233 MiB physical RAM, Arch Linux 7.2.15-1-omarchy Scene: startup/opening sky-and-moon movie, no loaded save; windowless, output requested 1280×720 and captures 1280×720 (startup renderer reports 1920×1080), frame generation off, render-scale override 100%, precompile and prediction off Method: a warm-up on each release-profile build, then 15-second before/after/before/after starts. Real process-local memory cap 7,639 MiB, swap forbidden, verified before execution. The same private, unshipped memory-query test double reports 7,639 MiB RAM / 32,767 MiB swap to the executable's startup notice on both builds; driver queries remain real. A memory cap alone does not change Linux's physical-memory query. Warning presence is the measurement, not frame time or memory savings. How to reproduce: from this PR run `python -I -B tests/test_low_memory_notice.py --cc gcc` (then `--cc clang`); for the negative control pass `--source ../main/host/hos_main.c`, where `../main` is a checkout of the named main. The fixture executes the production warning for 7,639 MiB RAM plus 32,767 MiB swap, with visible/headless spies, boundaries and query failure. For a real low-RAM Linux start, RAM below 10 GiB with RAM plus swap above 10 GiB reproduces the missing main warning. On a large-RAM PC the recorded windowless experiment additionally needs an unshipped executable-only `sysinfo` fixture returning those exact counts: a cgroup cap alone cannot reproduce that query. Use a fresh copied profile, the settings above, a verified 7,639-MiB/no-swap process scope and a 15-second wall stop; read the startup line before any lengthy load. The private query fixture is not a supported player switch. Current branch: `fix/linux-low-ram-warning` @ `15813ff4a5ee775e5925bee278ba74aa5ec9d2f5`, rebased onto main `d725b3631982ed0035ea3ac9cbe1677e9fad260c`. The previously published `ba1284a1` added only documentation after measured runtime `bf0802e7`; the rebase preserves that runtime and fixture byte for byte. The newer main differs from measured `d4a69456` only in scripts, docs and tests, with no game code, so the recorded game measurements still hold and no game run was repeated. | | main @ d4a69456 | this PR @ bf0802e7 | |---|---|---| | Low-physical-RAM warning lines, run 1 / run 2 | 0 / 0 | 1 / 1 | | Median warning lines per start | 0 | 1 | | Run order | Build | Warning lines | Game exit | |---|---|---:|---:| | before-1 | main @ d4a69456 | 0 | 124 | | after-1 | this PR @ bf0802e7 | 1 | 124 | | before-2 | main @ d4a69456 | 0 | 124 | | after-2 | this PR @ bf0802e7 | 1 | 124 | Exit 124 is the deliberately bounded startup ending at its wall limit. Both warm-ups and all four measured starts have zero fatal, guest-crash, device-loss and kernel-fault counts with complete journal coverage. These were ordinary shared runs, not speed measurements. ```text before-1: lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"} [hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply [hos host] boot: 7639 MB of memory, 32767 MB of swap warning lines: 0 after-1: lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"} [hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply [hos host] boot: LOW MEMORY: 7639 MB of memory, 32767 MB of swap; below 10240 MB of physical RAM: heavy swapping can make the game and desktop unresponsive (16 GB RAM or more recommended) warning lines: 1 before-2: lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"} [hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply [hos host] boot: 7639 MB of memory, 32767 MB of swap warning lines: 0 after-2: lowmem scope verified before game: {"memory.max": "8010072064", "memory.swap.max": "0", "memory.high": "max", "memory.oom.group": "0"} [hos host] boot: image 96 MB at 0x80000000, 9809 MB of memory for the game lowmem test double: executable sysinfo reports 7639 MiB RAM + 32767 MiB swap; real cgroup caps still apply [hos host] boot: LOW MEMORY: 7639 MB of memory, 32767 MB of swap; below 10240 MB of physical RAM: heavy swapping can make the game and desktop unresponsive (16 GB RAM or more recommended) warning lines: 1 base: 507 passed, 2 failed, 20 skipped in 504 s (linux, 6 at once) branch: 508 passed, 1 failed, 20 skipped in 175 s (linux, 6 at once) ``` In the retained pre-rebase suite, the branch failures were `tests/test_updater_asset_digest.py`. The shared measured-base suite also failed `tests/test_updater_asset_digest.py` with the same local .NET `NU1100` missing reference pack, and `tests/test_appimage_package_retry.py` in two timing-dependent fake-command cases under heavy load. That base AppImage test passed all nine cases in the separately requested isolated follow-up; the original full-suite failure remains reported. That d4a69456 base suite was run once for the moved pull requests and remains historical evidence, including its AppImage failure and isolated follow-up. The rebased source-check comparison follows below; no configured Forgejo runner replaces the local whole suite. ```text error NU1100: Unable to resolve 'Microsoft.AspNetCore.App.Ref (= 10.0.13)' for 'net10.0'. Base AppImage suite: FAILED (failures=2) Base AppImage isolated follow-up: Ran 9 tests in 15.166s; OK Before (new warning fixture against main, GCC and Clang): FAIL: wrong warning decision (swap must not hide low RAM on Linux) After (GCC and Clang, Linux and Windows-policy-on-Linux): PASS: production low-memory decisions, exact counts, message, headless and boot wiring ``` Windows-target fixture syntax passed; the Windows-policy execution on Linux is not Windows execution. The earlier Hookshot fork checks passed on Windows after the documented test-only wording repair; that is historical evidence, not a new Longshot Windows run. ### Rebased whole-suite comparison The whole suite was run after rebase on exact head `15813ff4a5ee775e5925bee278ba74aa5ec9d2f5`, including all documentation rows, with the repository's default compiler and a fresh test home. Main's `d725b363` suite is shared once across the moved pull requests. The missing local ASP.NET reference pack is the inherited `tests/test_updater_asset_digest.py` failure (`NU1100`); no new failure is attributed to this warning. | | main @ d725b363 | this PR @ 15813ff4 | |---|---|---| | Complete game-free suite on the rebased sources | 510 passed, 1 failed, 20 skipped | 510 passed, 1 failed, 20 skipped | ```text main @ d725b363: 510 passed, 1 failed, 20 skipped in 234 s (linux, 6 at once) this PR @ 15813ff4: 510 passed, 1 failed, 20 skipped in 241 s (linux, 6 at once) ``` ## Not tested Not tested: The visible dialog, real 8-GB hardware, Windows gameplay/full host build, AMD/Intel, long play and the reporter's failed session. No new hardware test request was posted. This warning cannot prevent a swap storm; absence of a warning does not guarantee sufficient memory. The historical Hookshot pressure runs still stalled, and their Water Temple load failure is not claimed fixed. Tested but not measured: the inspected opening movie continues on both builds; no frame-rate or overhead conclusion was taken from these shared starts. Historical pressure runs still stalled, as described above. ## Screenshots Nothing on screen is changed by these windowless starts; the visible warning dialog was not captured. Nothing changes on screen in these windowless starts: the warning is in the log. The dialog itself was not captured. **main @ d4a69456 (left); this PR @ bf0802e7 (right).** ![New Longshot before/after startup at the same movie frame. Both continue to the opening sky and moon; the warning difference is proved by the log, not a visible dialog.](https://git.magicbean.dev/attachments/a8b16803-7598-4f70-8d4c-813fb2fb628d) **Historical context, not a matched comparison:** main @ 51da0464 and this PR @ c5708cb0 (the original Hookshot warning patch). ![Historical Hookshot evidence from 2026-11-12, main 51da0464 and the original warning patch: roomy Water Temple control, last capture before the pressure-stalled load, and warning-build loading screen. Different states, not a matched before/after or new Longshot result.](https://git.magicbean.dev/attachments/b58fcaf1-d14c-43ce-8988-365e8e74406f) ## Risk and rollback The advisory notice can be too cautious for a particular small scene, and a failed memory query must not invent a warning. It does not bound allocation, stop a swap storm or diagnose the Water Temple failure; the game continues after warning. Windows must retain its old RAM-plus-page-file decision. There is no new opt-out flag: reverting the Linux warning change and its guidance is sufficient; `HOS_HEADLESS` hides only the dialog, not the warning or memory pressure. ## Reviewer notes Start with `memory_notice_text()` and `memory_notice()` in `host/hos_main.c`, then the nine RAM/swap cases, query-failure checks and visible/headless spies in `tests/test_low_memory_notice.py`. Verify Linux physical RAM versus the unchanged Windows policy and its different continuation text. The older pressure experiment and current warning proof are deliberately separate; allocator changes, OOM policy and the reporter's freeze diagnosis are not part of this PR. ## Issues See https://github.com/NotRexed/Hookshot/issues/2838 and https://github.com/NotRexed/Hookshot/issues/1241. The warning does not close the freeze report. Original pull request: https://github.com/NotRexed/Hookshot/issues/2901. No matching issue was present in the checked Longshot issue inventory; these are historical GitHub numbers, not Forgejo issue numbers. ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Not tested. - [x] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Flags noted, and the switch reference updated (docs/development.md, the README). — Test controls are documented in the fixture; existing headless semantics are unchanged, and README memory guidance is updated. - [x] A row in `docs/tested-configurations.md` for each measured run. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Docs updated. --- Moved from NotRexed/Hookshot#2901. Assisted-by: GPT-6 Astra Co-Authored-By: GPT-6 Astra <[email protected]>
The existing 10 GiB RAM-plus-swap check hides the warning on an 8 GB Linux PC with a large swap area. Warn below that conservative physical-RAM floor without changing allocations or Windows behavior. Exercise the reported 7639/32767 MiB case, headless and visible paths with deterministic memory-query spies, and stop presenting 10 GB as a runtime footprint ceiling.

Refs #2838 and #1241. This is warning coverage, not a fix for the unobserved failed session.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
Keep the failed initial route control visible. The 24 GiB control reaches Water Temple; the 7639 MiB / 8 GiB swap model stalls after an accepted transition without an OOM kill or GPU fault. The warning build logs the reported RAM/swap pair under a logging-only query test double, but still stalls while loading. No claim that the warning fixes the freeze.

The Water Temple control reaches about 19 GiB resident, so extend the documented observed range rather than keeping 17 GiB as an apparent ceiling.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
The Windows fixture executed successfully until its shared wording assertion expected the Linux-only phrase. Keep the runtime unchanged: assert the existing Windows text, "It starts now anyway.", and its RAM-plus-page-file rule separately from Linux physical-RAM guidance.

On Linux, compile a second fixture with _WIN32 selected after the host headers, retaining the native environment API. Both policies run with GCC and Clang; the native Windows target passes the fixture preflight. Actual Windows execution of this repair remains for the next fork run.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
Keep the scoped startup query-double proof separate from the historical pressure investigation. Correct the requirements link after the README filename change.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
mooki changed title from fix(linux): warn about low physical RAM even with ample swap to WIP: fix(linux): warn about low physical RAM even with ample swap 2026-11-13 00:58:52 +00:00
Author
First-time contributor

Back to work in progress, for its description only. This was opened shortly before #48 merged and follows the earlier template, so it does not pass the new description check (no Flags and settings and no Risk and rollback section, table columns named Before and After). The code and the measurements are unchanged: the whole suite passes on this exact commit apart from one local .NET failure that also fails on main. The description is being moved to the new template and the branch rebased onto d725b363; it comes back through pr ready once the check passes.

Back to work in progress, for its description only. This was opened shortly before #48 merged and follows the earlier template, so it does not pass the new description check (no Flags and settings and no Risk and rollback section, table columns named Before and After). The code and the measurements are unchanged: the whole suite passes on this exact commit apart from one local .NET failure that also fails on main. The description is being moved to the new template and the branch rebased onto d725b363; it comes back through `pr ready` once the check passes.
Author
First-time contributor

Updated the description to the current template, including the test controls, reproduction steps, named measurement commits, risk/rollback and reviewer notes; the uploaded pictures and earlier evidence are preserved. Rebased onto main d725b363 without changing the four patches, and the whole suite on 15813ff4 reports 510 passed, 1 failed and 20 skipped, with only the same local .NET NU1100 failure as main. The game observations remain pinned to their actual measured commits because the newer main changes only scripts, docs and tests; the description checker passes without --wip.

Updated the description to the current template, including the test controls, reproduction steps, named measurement commits, risk/rollback and reviewer notes; the uploaded pictures and earlier evidence are preserved. Rebased onto main `d725b363` without changing the four patches, and the whole suite on `15813ff4` reports 510 passed, 1 failed and 20 skipped, with only the same local .NET `NU1100` failure as main. The game observations remain pinned to their actual measured commits because the newer main changes only scripts, docs and tests; the description checker passes without `--wip`.
mooki changed title from WIP: fix(linux): warn about low physical RAM even with ample swap to fix(linux): warn about low physical RAM even with ample swap 2026-11-13 01:29:50 +00:00
mooki force-pushed fix/linux-low-ram-warning from ba1284a1f1 to 15813ff4a5
All checks were successful
PR description / Description follows the template (pull_request_target) Successful in 2s
2026-11-13 01:29:50 +00:00
Compare
mooki changed title from fix(linux): warn about low physical RAM even with ample swap to WIP: fix(linux): warn about low physical RAM even with ample swap 2026-11-13 01:48:33 +00:00
Author
First-time contributor

Back to work in progress for two reasons, neither a change to the code or the measurements. The template gained a Testing section with #72 (what was tested, what was not, and which testers are needed, with test requests), which this description does not have yet. And #39's merge added a row to the results table at the same place as this pull request's rows, so the branch conflicts in that one file until it is rebased. Both are being done; it returns through pr ready.

Back to work in progress for two reasons, neither a change to the code or the measurements. The template gained a Testing section with #72 (what was tested, what was not, and which testers are needed, with test requests), which this description does not have yet. And #39's merge added a row to the results table at the same place as this pull request's rows, so the branch conflicts in that one file until it is rebased. Both are being done; it returns through `pr ready`.
All checks were successful
PR description / Description follows the template (pull_request_target) Successful in 2s
This pull request has changes conflicting with the target branch.
  • docs/tested-configurations.md
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/linux-low-ram-warning:mooki-fix/linux-low-ram-warning'
git switch 'mooki-fix/linux-low-ram-warning'
Sign in to join this conversation.
No description provided.