This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Sylpheed RE agent 7150827e96 tools+docs: the freeze from inside - all 79 threads are in a wait, and two of them burn CPU cycling
The gdb route works, and the recipe is written down: run-canary execs $XENIA_BIN,
so a wrapper that execs "gdb --args <real binary>" keeps the lockfile, the flags
and the process name (gdb forks and execs the real binary, so ps -C xenia_canary
still finds the inferior) while satisfying ptrace_scope=1 by being the parent.
The Release binary is not stripped - 26595 symtab entries - so frames have names.
The handle SIGSEGV/SIGBUS/SIG32-35 lines are mandatory: xenia uses SIGSEGV for
guest memory watches and the RT signals for thread suspend.

A run froze after ~4 minutes of flight, screen still "flight" rather than GAME
OVER, and all 79 threads had backtraces. EVERY ONE is in a wait - guest threads
in KeWaitForSingleObject / NtWaitForSingleObjectEx / SelfSuspend, the GPU command
processor parked idle, the main thread in poll().

It is nevertheless burning 1253 ticks per 10 s: 403 in the TimerQueue thread
(nanosleep inside TimerThreadMain) and 290 + 274 in two guest threads that the
backtrace shows blocked in KeWaitForSingleObject. A thread genuinely blocked
cannot burn 28% of a core, so those two are CYCLING - a timed wait that expires
and is re-entered - with the timer thread servicing them hot. Three samples
minutes apart show identical frames.

That refines the earlier "the guest is spinning, not deadlocked": the CPU burn is
real but it is in the WAIT PATH inside the kernel layer, not in guest code. The
shape is an event that never gets signalled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
2026-08-24 01:13:01 +00:00

24 lines
1.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Take a backtrace of every thread of an emulator that is running under gdb.
#
# Pair with the wrapper at /sylph-home/re/bin/gdb-wrap/xenia_canary (see
# docs/re/mission-freeze-resume-spin.md): ptrace_scope=1 forbids attaching to a
# running emulator, so it has to be STARTED under gdb.
#
# SIGINT to gdb stops the inferior; commands then go in through the command file
# the wrapper is tailing, and the answer comes back in the gdb log. `continue` at
# the end so the run can carry on.
set -u
CMD="${GDB_CMD_FILE:-/tmp/gdb-cmd}"
OUT="${GDB_OUT_FILE:-/tmp/gdb-out.log}"
DEPTH="${1:-12}"
pid=$(pgrep -x gdb | head -1)
[ -n "$pid" ] || { echo "no gdb process — was the emulator started with XENIA_BIN=/sylph-home/re/bin/gdb-wrap/xenia_canary ?"; exit 1; }
mark="=== BT $(date +%s) ==="
before=$(wc -c < "$OUT")
kill -INT "$pid"
sleep 3
{ echo "echo $mark\\n"; echo "info threads"; echo "thread apply all bt $DEPTH"; echo "echo === END ===\\n"; echo "continue"; } >> "$CMD"
sleep 8
tail -c +$((before + 1)) "$OUT"