From 5ecdb1c4603c12dcdd9a607e160ae1faf005291a Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Wed, 26 Aug 2026 18:12:35 +0000 Subject: [PATCH] re: the freeze requires the rasterizer -- --gpu=null does not freeze The cleanest control available, and it settles which side the bug is on. Xenia has a null graphics backend. Same ISO, same route, same presses: lavapipe --gpu=null Main XThread CPU 0 ms / 3 s 3860 ms / 4 s state / wchan S / futex_do_wait R / not blocked guest memory churn ~0 (18 B of 8.2 MB) 22.6% of 6 MB in 4 s allocations stall 114 -> 120, no failures process CPU 265% (all llvmpipe) 330% (mostly guest) With no rasterizer the guest does not freeze: it runs at close to a full core and walks through the content load -- the exact point that hangs every rendered run. So the fault is in the host rendering path, which explains why every game-side hypothesis on that page was refuted in turn. Blocked, and recorded as such rather than improvised around: deciding whether lavapipe is deadlocked or merely taking hours over one pathological draw needs hardware Vulkan, which this container does not have. Six minutes of nine saturated llvmpipe threads with no frame is suggestive, not conclusive. Amber workaround: --gpu=null gives a live guest, and everything the backlog needs -- entity positions, flight model, world unit -- is read from guest memory, not pixels. The gap is navigation: menu-walking is screenshot-driven, and blind A presses advanced allocations 114 -> 120 but never reached a mission (DEF_VTABLE and INST_VTABLE scans both 0). Next step is to drive navigation from guest memory instead of the screen, which is engineering rather than mystery. --- docs/re/BACKLOG.md | 20 +++++++++ docs/re/mission-freeze-heap-exhaustion.md | 53 +++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 2d1f43e..56f4905 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -6,6 +6,26 @@ unknown, what evidence exists, and what the first step would be. Move an item in --- +## 🔴 BLOCKER — the mission freeze is a software-rendering hang (2026-08-26) + +The freeze that blocks every dynamic measurement is in the **host rendering +path**, proven by control: with `--gpu=null` the guest runs at ~1 core through +the same content load that hangs every rendered run, with zero allocation +failures, while under `lavapipe` `Main XThread` sits at 0 ms CPU in +`futex_do_wait` and nine `llvmpipe` threads saturate for six minutes without +producing a frame. + +**Deciding whether `lavapipe` is deadlocked or merely pathologically slow needs +hardware Vulkan, which this container does not have.** That is a stated container +limit, so it is recorded here rather than worked around. + +🟡 **Workaround with a gap:** `--gpu=null` gives a live guest, and everything the +backlog needs is read from guest memory, not pixels. What is missing is +navigation — menu-walking is screenshot-driven today, and blind Ⓐ presses reached +no mission (`DEF_VTABLE` scan 0/0). **First step: drive navigation from guest +memory instead of the screen.** +See [`mission-freeze-heap-exhaustion.md`](mission-freeze-heap-exhaustion.md). + ## 🧰 The boot path — three failures that look like the emulator and are not (2026-08-26) * ✅ **`--audio` prevents boot outright.** `run-canary`'s own header says the flag diff --git a/docs/re/mission-freeze-heap-exhaustion.md b/docs/re/mission-freeze-heap-exhaustion.md index 0b16197..3f54d6f 100644 --- a/docs/re/mission-freeze-heap-exhaustion.md +++ b/docs/re/mission-freeze-heap-exhaustion.md @@ -946,3 +946,56 @@ command processor has already handed off and is itself waiting. ⚠️ **Method rule earned the hard way: do not diagnose a performance or liveness question under a debugger.** Use it to read state at a known-good stopping point, then re-measure timing and CPU with it detached. + +--- + +# ✅✅ The freeze REQUIRES the rasterizer — `--gpu=null` does not freeze + +**2026-08-26.** The cleanest control available, and it settles which side the bug +is on. Xenia has a null graphics backend (`--gpu=null`, `xenia_main.cc:415`). +Same ISO, same route, same presses: + +| | lavapipe (default) | **`--gpu=null`** | +|---|---|---| +| `Main XThread` CPU | **0 ms / 3 s** | **3 860 ms / 4 s** | +| `Main XThread` state | `S` | **`R` (running)** | +| `Main XThread` wchan | **`futex_do_wait`** | **`0` (not blocked)** | +| guest memory churn | ~0 (18 bytes / 8.2 MB) | **22.6 %** of 6 MB in 4 s | +| allocations across the content load | stall | **114 → 120, zero failures** | +| process CPU | 265 % (all `llvmpipe`) | 330 % (mostly the guest) | + +**With no rasterizer the guest does not freeze.** It runs at close to a full core +and walks through the content load — the exact point that hangs every rendered +run — without a single allocation failure. + +So the fault is in the **host rendering path**, and every game-side hypothesis +this page worked through was looking in the wrong place. That is now explained +rather than merely observed. + +## 🔴 Blocked: telling "stuck" from "pathologically slow" needs hardware Vulkan + +The remaining question about the rasterizer itself — whether `lavapipe` is +deadlocked or merely taking hours over one pathological draw — cannot be answered +here. This container has **software rendering only**, and that is one of the +limits `AGENT.md` names explicitly. Six minutes of nine saturated `llvmpipe` +threads with no frame produced is suggestive, not conclusive, and no amount of +further waiting settles it. **Recorded as a blocker rather than improvised +around.** + +## 🟡 `--gpu=null` is a promising oracle for memory-based work — with one gap + +Everything this project actually needs from a running game is read out of guest +memory: entity positions, the flight model, the world unit. None of it needs +pixels. `--gpu=null` supplies a live guest for exactly that. + +The gap is **navigation**. Menu-walking is currently driven by screenshots, and +with no rasterizer there is nothing to look at. Pressing Ⓐ blind got the guest +through several screens — allocations advanced 114 → 120 — but never into a +mission: a `DEF_VTABLE` / `INST_VTABLE` scan afterwards returns **0 / 0**, so no +units were ever loaded. + +❔ Next, and it is a tractable engineering task rather than a mystery: **navigate +by guest memory instead of by screen.** The menu state must be readable — the +cleared-stage mask at `0x828F40C0` is already known and pokeable, so the menu +layer keeps its state somewhere findable. A memory-driven `nav_to_flight` would +make `--gpu=null` a complete oracle for every measurement on the backlog.