Files
Sylpheed/tools/diagnose-freeze.sh
sim 94f84b1356
All checks were successful
CI / Native — linux (pull_request) Successful in 2h16m47s
CI / WASM — Web (pull_request) Successful in 31m15s
CI / Formatting (pull_request) Successful in 1m19s
chore: hand the workspace over — the gated launchers, and the state of play
Resuming happens on the other machine, so anything that lived only in this
workspace either comes into the repo or gets named as something to carry.

**The launchers come in.** `run-canary-safe.sh` (Wine) and
`run-canary-native-safe.sh` (native) are the ONLY sanctioned way to start Canary
from the editor — they force software Vulkan and refuse to launch while a
hardware Vulkan device is visible, because Canary on the AMD GPU takes VS Code
with it. They sat in the workspace root, outside git, hardcoding one machine's
absolute paths, which is exactly why they could not be checked in. They now
derive the workspace from their own location and honour `$SYLPHEED_ISO` and
`$CANARY_BIN`, so the layout is a default rather than a requirement. Same for
`run-canary-native.sh` (interactive, hardware Vulkan — not from the IDE),
`diagnose-freeze.sh`, `live-guest-state.sh`, `heaptrack-wrap.sh` and the
`asound-null.conf` the native launcher needs beside it.

Both safe launchers were run from `tools/` before this commit: the native one
reached content in 20 s (`VERDICT: HEALTHY`, title + 25,398 XMA lines, no
faults), the Wine one ran 25 s and logged 4 `ADV.wmv` hits.

**`docs/agents/HANDOFF-2026-09-18.md`** records what changed since 2026-09-16,
what is on the server, what cannot travel through git, and the traps this machine
paid for — chiefly that the guest-PC branch probe exists only on the fork's
snapshot branch, so a rebuild from `sylpheed-re` silently loses it.

**`HANDOFF-2026-09-06.md`** gets a correction note rather than an edit: a plain
clone works again now that the 545 MB branch is gone, and its baselines are two
baselines old.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 07:17:36 +02:00

59 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Freeze autopsy for a LIVE (hung) Xenia-Canary process.
#
# When the game or the emulator freezes, DO NOT kill it. Run this instead: it
# attaches gdb to the running process and dumps a backtrace of every thread,
# which names exactly who is stuck and on what (the guest audio callback, a
# kernel lock, the GPU present, an XMA context lock, ...).
#
# The Release binary is NOT stripped, so we get real function names.
#
# Usage: ./diagnose-freeze.sh [output_file]
# Safe: read-only. gdb detaches afterwards and the process keeps running, so
# you can dump twice and diff -- if two dumps 10s apart are identical, it is a
# true deadlock, not slow progress.
set -u
OUT="${1:-/tmp/canary_freeze_$(date +%H%M%S).txt}"
PID=$(pgrep -x xenia_canary | head -1)
if [ -z "$PID" ]; then
echo "No running xenia_canary process found (is it still up? don't kill it!)."
exit 1
fi
command -v gdb >/dev/null || { echo "ABORT: gdb not installed."; exit 4; }
echo "Attaching to xenia_canary (pid $PID) -- read-only, it keeps running."
{
echo "=== xenia_canary freeze autopsy pid=$PID $(date) ==="
echo
echo "--- /proc/$PID/status ---"
grep -E "^(State|Threads)" "/proc/$PID/status" 2>/dev/null
echo
echo "--- per-thread kernel wait channel (who is blocked, cheap) ---"
for t in /proc/"$PID"/task/*; do
tid=$(basename "$t")
printf " tid %-7s state=%-2s wchan=%-24s %s\n" \
"$tid" \
"$(awk '{print $3}' "$t/stat" 2>/dev/null)" \
"$(cat "$t/wchan" 2>/dev/null || echo '-')" \
"$(cat "$t/comm" 2>/dev/null)"
done
echo
echo "--- all thread backtraces (gdb) ---"
} > "$OUT"
gdb -p "$PID" -batch \
-ex "set pagination off" \
-ex "set confirm off" \
-ex "thread apply all bt" \
-ex "detach" 2>&1 | tee -a "$OUT" > /dev/null
echo "Wrote: $OUT"
echo
echo "--- threads that look blocked ---"
grep -E "^Thread |pthread_cond_wait|futex|__lll_lock|Wait|Acquire" "$OUT" | head -40
echo
echo "Full dump: $OUT (run again in ~10s and diff to confirm a true deadlock)"