re: SOLVED -- the mission freeze is a modal sign-in dialog

Every Xam UI dialog goes through xeXamDispatchDialog, and the calling guest
thread blocks on fence.Wait() until it is dismissed.  With kernel logging on the
last call before the freeze is XamShowSigninUI(00000001, 00000001): the game
asks for a signed-in profile, Xenia opens a modal dialog, and nothing in a
scripted run ever dismisses an ImGui dialog.

That accounts for every symptom at once -- Main XThread futex-blocked at 0 ms CPU
rather than spinning, emulator alive, no guest progress, no faults, and
independence from both the GPU backend and the allocation outcome.

Fix: run-canary --logged_profile_slot_0_xuid=B13EBABEBABEBABE.  Same route, one
variable changed:

                        no profile      with profile
    screen id           4, forever      4 -> 5 -> 6 -> 8 -> 9 -> 10
    XamShowSigninUI     called          not called
    alloc failures      1               0
    guest throws        1               0
    guest churn         0.000%          1.006%

XamShowDeviceSelectorUI is then requested but storage_selection_dialog defaults
to false, so it is not shown and does not block.

Why it took so long: --log_mask=13, used by every script in this corpus,
DISABLES kernel logging -- the one category that names the dialog.  Without it
the freeze presents as a bare futex block, which is why it was attributed in
turn to a heap leak, rounding, MmQueryStatistics, a build regression, the route,
the savegame, shader compilation, an infinite guest loop and the software
rasterizer, each refuted in its own section.

Nearest miss worth recording: challenge-mission-gate.md reported a "Disc Read
Error" dialog on this failure.  That is XamShowDirtyDiscErrorUI, which calls
exit(1) -- "This is death, and should never return" -- so it cannot be our
freeze, whose process stays alive.  Checking that distinction is what led to the
dialog mechanism.

Open: no mission reached yet (DEF_VTABLE/INST_VTABLE still 0 at screen 10), so
the remaining screens are menus.  Ordinary navigation, not a blocker.
This commit is contained in:
Sylpheed RE agent
2026-08-26 18:41:09 +00:00
parent 18e9cecf21
commit d712e5aa1a
2 changed files with 81 additions and 0 deletions

View File

@@ -6,6 +6,18 @@ unknown, what evidence exists, and what the first step would be. Move an item in
---
## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26)
`XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the
calling guest thread on `fence.Wait()` until it is dismissed — which nothing in a
scripted run ever does. **Fix: pass `--logged_profile_slot_0_xuid=…`.** Same
route, one variable: screen id goes from stuck at **4 forever** to
**4 → 5 → 6 → 8 → 9 → 10**, allocation failures 1 → **0**, guest throws 1 → **0**,
guest churn 0.000 % → **1.006 %**.
It hid for so long because `--log_mask=13` (used by every script here)
**disables kernel logging**, the one category that names the dialog.
See [`mission-freeze-signin-dialog.md`](mission-freeze-signin-dialog.md).
## 🔴 ~~BLOCKER — the mission freeze is a software-rendering hang~~ WITHDRAWN (2026-08-26)
> **Withdrawn the same day.** Driving the null backend blind to the *same* screen

View File

@@ -0,0 +1,69 @@
# ✅✅ The freeze is `XamShowSigninUI` — a modal dialog nobody can dismiss
**Root-caused 2026-08-26**, after a long chain of wrong answers recorded in
[`mission-freeze-heap-exhaustion.md`](mission-freeze-heap-exhaustion.md).
## The mechanism, from Xenia's source
Every Xam UI dialog goes through `xeXamDispatchDialog` (`xam_ui.cc:60`), and the
calling **guest thread blocks**:
```cpp
xe::threading::Fence fence;
if (app_context.CallInUIThreadSynchronous(
[&dialog, &fence]() { dialog->Then(&fence); })) {
fence.Wait(); // <- the guest thread stops here until dismissed
```
With kernel logging enabled (`--log_mask=0`; note **`log_mask` disables**
categories, so the `--log_mask=13` used throughout this corpus hides exactly
this), the last kernel call before the freeze is:
d> F8000008 XamShowSigninUI(00000001, 00000001)
The game asks for a signed-in profile, Xenia opens a modal sign-in dialog, and
the guest waits on the fence **forever** — nothing in a scripted run dismisses an
ImGui dialog.
That accounts for every symptom at once: `Main XThread` **futex-blocked at 0 ms
CPU** rather than spinning; the emulator alive and healthy; no guest progress; no
faults; and independence from both the GPU backend and the allocation outcome.
## ✅ The fix, and the before/after
`run-canary` accepts `--logged_profile_slot_0_xuid=B13EBABEBABEBABE`. Same route,
same inputs, one variable changed:
| | without a profile | **with `--logged_profile_slot_0_xuid`** |
|---|---|---|
| screen id reached | **4, forever** | **4 → 5 → 6 → 8 → 9 → 10** |
| `XamShowSigninUI` | **called** | not called |
| allocation failures | 1 | **0** |
| guest throws | 1 | **0** |
| guest churn | 0.000 % (19 B of 8 MB) | **1.006 %** (81 KB of 8 MB) |
The game walks through six further screens where it previously sat at one
forever. `XamShowDeviceSelectorUI` is then requested, but
`storage_selection_dialog` defaults to **false**, so that dialog is not shown and
does not block.
## 🔴 Why this took so long — and what it invalidates
The `--log_mask=13` used by every script in this corpus **disables kernel
logging**, which is the one category that names the dialog. Without it the freeze
presents as a bare futex block with no explanation, which is why it was
attributed in turn to a heap leak, allocation rounding, `MmQueryStatistics`, a
build regression, the navigation route, the savegame, shader compilation, an
infinite guest loop, and finally the software rasterizer — each refuted in its
own section.
⚠️ The nearest miss is worth recording: `challenge-mission-gate.md` reported
Xenia showing a *"Disc Read Error"* on this failure. That is a **different**
dialog (`XamShowDirtyDiscErrorUI`), and it calls `exit(1)` — "This is death, and
should never return" — so it cannot be our freeze, whose process stays alive.
Checking that distinction is what led to the dialog mechanism.
❔ Still open: a mission has not been reached yet — `DEF_VTABLE` / `INST_VTABLE`
scans are still 0 at screen 10, so the remaining screens are menus (mission
select, briefing, ready room). That is now ordinary navigation work, not a
blocker.