docs/re: the cache-flush throw — a 100-second trigger, and two withdrawals
Chasing the title-screen crash into the emulator's own diagnostics turned it from a mystery into a controlled experiment, and knocked over two things this corpus said yesterday. Withdrawn #1: "the fault address 0x1_0000000C is a pointer with a stale high word". The crash dump prints r25 = 0x0000000C, clean. Xenia maps the guest's 4 GiB at host 0x1_00000000, so that IS guest address 12. The guest dereferenced the small integer 12. Withdrawn #2: "with --mem_watch=false the crash does not happen at all", which named the crash-oracle handoff's suspect #1 as measured. It was confounded — every --mem_watch=false run had also had a warm cache. Held cold, the throw happens with the probe off (2 437 crash dumps). mem_watch is eliminated for this crash. What it actually is: the access violation is the guest's own `throw` RETURNING, because this build logs guest C++ exceptions and continues rather than unwinding. So the event is the throw, and with --cache_throw_diag=true the guest names it: std::out_of_range, from the cache-manager flush, with a deque of 38 entries (37 distinct, one duplicated) against a 37-key map, every one of them absent from the flush's snapshot but present in the live map — the TOCTOU race the logger's own message describes. And the new, useful part: the trigger is the on-disc cache. Complete cache, no throw (2 runs). Directory moved aside or half-rebuilt, throw ~100 s into the boot (3 runs, including one that threw with NO access violation behind it — which is why crash dialogs are the wrong thing to count). A suspect in that bisection plan now costs a `mv` and two minutes instead of a mission.
This commit is contained in:
@@ -89,20 +89,19 @@ below. Two later attempts to reproduce it (open the panel, close it, press Ⓐ)
|
||||
produced neither a crash nor a transition. So it is one data point that Ⓐ *can*
|
||||
reach code the title does not otherwise run, and nothing more.
|
||||
|
||||
**The reproducible crash is the boot-time content path.** With the default
|
||||
`--mem_watch=true`, in two independent runs, the guest dies with an access
|
||||
violation reading `0x00000001_0000000C` at PC `0x82307128` on guest thread 9,
|
||||
right after `HostPathDevice::ResolvePath(\aab216c3\5\c10eae6)` and a
|
||||
`RtlRaiseException(E06D7363)` (a C++ throw). Xenia pauses itself and stacks up
|
||||
crash dialogs — 991 in one run. With `--mem_watch=false` that crash does not
|
||||
happen at all.
|
||||
**The reproducible crash is the cache flush, and it is not what it looked like.**
|
||||
With the default `--mem_watch=true`, in two runs, the guest died with an access
|
||||
violation at PC `0x82307128` right after `RtlRaiseException(E06D7363)`. Chasing
|
||||
that produced a correction and a cheap trigger, both in
|
||||
[`title-crash-stl-tree.md`](title-crash-stl-tree.md):
|
||||
|
||||
That pairing — crash with the memory-probe thread on, none with it off, both in a
|
||||
save/content path — matches the suspect ranked #1 in
|
||||
`xenia-canary/HANDOFF-crash-oracle-2026-07-16.md`, whose crash was also a guest
|
||||
C++ exception in a cache/save path. This is a second, far cheaper reproduction of
|
||||
it: at the **title screen**, ~40 s from a cold boot, instead of in the Ready Room
|
||||
after a mission.
|
||||
* the access violation is a **consequence** of the guest's own `throw` returning
|
||||
(this build does not unwind guest EH), so the event to study is the throw;
|
||||
* the throw is `std::out_of_range` from the game's **cache-manager flush**, and
|
||||
an **incomplete on-disc cache** triggers it ~100 s into a boot;
|
||||
* the observation that started this — "crash with `--mem_watch=true`, none with
|
||||
`--mem_watch=false`" — was **confounded** by cache warmth, and is withdrawn:
|
||||
cold cache with the probe off throws just the same.
|
||||
|
||||
**The first of those next steps is done**, and it moves the crash out of this
|
||||
entry into its own: `0x82307128` is inside an MSVC `std::map`/`set` **erase** —
|
||||
|
||||
Reference in New Issue
Block a user