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.
This commit is contained in:
Sylpheed RE agent
2026-08-26 18:12:35 +00:00
parent ffdccba655
commit 5ecdb1c460
2 changed files with 73 additions and 0 deletions

View File

@@ -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

View File

@@ -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.