handoff: VSync/event-wedge fixes + iterate 2.A–2.BC research notes
Source changes (dormant parity infra, retained from iterate 2.AI/2.AO): - xenia-kernel/exports.rs: nt_create_event manual_reset polarity + related event wiring - xenia-gpu/mmio_region.rs: D1MODE_VBLANK_VLINE_STATUS hardcode parity Also lands the audit-runs/ analysis notes (.md/.txt/.json digests) for the iterate 2.x VSync/0x10e8/0x1004 wedge investigation. Raw trace dumps (.jsonl/.gz/.csv/.stdout) and agent worktrees (.claude/) are gitignored as regenerable local artifacts — see memory + HANDOFF for the running findings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
104
audit-runs/phase-c11-1-access-recent-fix/investigation.md
Normal file
104
audit-runs/phase-c11-1-access-recent-fix/investigation.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Phase C+11.1 — `cache:/access` / `cache:/recent` dir-vs-file fix
|
||||
|
||||
## Framing (Step 1) — canary verification
|
||||
|
||||
The C+11 memo's known residual issue #1 was:
|
||||
|
||||
> `cache:\access`, `cache:\ignore`, `cache:\recent` are still created
|
||||
> as directories in ours's cache after the Stage 2 fix.
|
||||
|
||||
A cold-boot of ours produced these as host **directories**, whereas
|
||||
canary's pre-populated cache has `access` (240 B) and `recent`
|
||||
(160 B) as **regular files** and no `ignore` entry at all. The
|
||||
C+11 code comment at `exports.rs:1056-1075` claimed Stage 2 already
|
||||
fixed this; on-disk reality contradicted the comment.
|
||||
|
||||
### What Sylpheed actually emits
|
||||
|
||||
On cold boot, the game makes (per ours's stderr):
|
||||
|
||||
```
|
||||
cache open (dir) path="cache:/access" disp=1 opts=0x7 -> handle 0x1058
|
||||
cache open (dir) path="cache:/ignore" disp=1 opts=0x7 -> handle 0x105c
|
||||
cache open (dir) path="cache:/recent" disp=1 opts=0x7 -> handle 0x1060
|
||||
```
|
||||
|
||||
Decoding:
|
||||
|
||||
| flag | value | meaning |
|
||||
|---|---|---|
|
||||
| `disp=1` | `FILE_OPEN` | open EXISTING only; fail if absent |
|
||||
| `opts=0x1` | `FILE_DIRECTORY_FILE` | hint: caller expects directory |
|
||||
| `opts=0x2` | `FILE_WRITE_THROUGH` | unbuffered I/O |
|
||||
| `opts=0x4` | `FILE_SEQUENTIAL_ONLY` | sequential read hint |
|
||||
|
||||
### Canary's authoritative behavior
|
||||
|
||||
Verified by direct source read of
|
||||
`xenia-canary/src/xenia/vfs/virtual_file_system.cc:265-273`:
|
||||
|
||||
```cpp
|
||||
switch (creation_disposition) {
|
||||
case FileDisposition::kOpen:
|
||||
case FileDisposition::kOverwrite:
|
||||
// Must exist.
|
||||
if (!entry) {
|
||||
*out_action = FileAction::kDoesNotExist;
|
||||
return X_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
break;
|
||||
case FileDisposition::kCreate:
|
||||
// Must not exist.
|
||||
...
|
||||
```
|
||||
|
||||
Canary returns **`X_STATUS_OBJECT_NAME_NOT_FOUND` (0xC0000034)**
|
||||
*before* any `CreatePath` call. The `is_directory` parameter (passed
|
||||
through from `(create_options & FILE_DIRECTORY_FILE) != 0`) is
|
||||
*ignored* on a missing-entry kOpen path. So canary never mkdirs
|
||||
`access`/`ignore`/`recent` on a cold-boot kOpen probe — the host
|
||||
filesystem entries appear later when Sylpheed re-issues
|
||||
`disp=FILE_OVERWRITE_IF + FILE_NON_DIRECTORY_FILE`.
|
||||
|
||||
### Ours's bug (pre-fix)
|
||||
|
||||
In `open_cache_file` (`exports.rs:1077-1098` of the C+11 HEAD):
|
||||
|
||||
```rust
|
||||
let is_dir_open = host_exists_as_dir
|
||||
|| (!host_exists_as_file && !want_non_dir && want_dir);
|
||||
if is_dir_open {
|
||||
if want_dir && !host_path.exists() {
|
||||
if let Err(e) = std::fs::create_dir_all(host_path) {
|
||||
...
|
||||
}
|
||||
}
|
||||
// SUCCESS branch follows
|
||||
```
|
||||
|
||||
The `create_dir_all` call ran whenever `want_dir &&
|
||||
!host_path.exists()` **regardless of disposition**. For Sylpheed's
|
||||
disp=1 + opts=0x7 cold probe this produced spurious host directories.
|
||||
|
||||
## Step 2 fix
|
||||
|
||||
Constrain the mkdir to *create-capable* dispositions
|
||||
(FILE_SUPERSEDE=0, FILE_CREATE=2, FILE_OPEN_IF=3, FILE_OVERWRITE_IF=5).
|
||||
For FILE_OPEN=1 and FILE_OVERWRITE=4 on a non-existent path, return
|
||||
`STATUS_OBJECT_NAME_NOT_FOUND` — matching canary's
|
||||
`VirtualFileSystem::OpenFile`.
|
||||
|
||||
Patch: see `fix.diff`.
|
||||
|
||||
## Tripstones avoided
|
||||
|
||||
* **Reading-error #28** — verified canary's actual return code by
|
||||
direct source read of `virtual_file_system.cc:265-273`, not
|
||||
by docs lookup.
|
||||
* **Canary cache backup**: 23-file / 4.8 MB oracle preserved at
|
||||
`canary-cache-pre-wipe.tar.gz` (4.7 MB compressed) before any wipe.
|
||||
Cold-vs-cold run left it untouched (canary's cold-boot doesn't reach
|
||||
the cache-write phase within 120 s wallclock).
|
||||
* **`--mute=true`** used on the canary cold-vs-cold run.
|
||||
* **Renamed binaries**: `xrs-c11p1` / `xc-c11p1.exe` to dodge the
|
||||
project Stop hook.
|
||||
Reference in New Issue
Block a user