You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Live-captured from a wedged real session (macOS aarch64, main 8d27f7b964 build, ~17 min into authenticated use). The most severe TUI defect observed: total dispatch stop while every component looks alive.
The user-visible sequence
Long conversation → large paste → question submitted → response spinner (Transmuting… (43s)) → counter freezes at 43s → all input dead (typing, ESC, Ctrl-C — nothing echoes or interrupts; raw mode, so Ctrl-C is an in-app byte, not a signal) → stays wedged indefinitely (>10 min). Memory flat at 680 MB throughout (no allocation → not processing).
An earlier, milder sighting in the same session (#9587): multi-second freeze during busy work that then batch-drained on its own. This one never drained. Likely the same defect at different severities; keypress explicitly did NOT unstick either (that hypothesis is dead).
The forensics (5s sample, all preserved)
Main thread (4158/4158 samples): cycling kevent (3988 in the syscall) + clock_gettime bursts — the loop parks, wakes, checks deadlines, re-parks. It is not stuck; it dispatches nothing.
stdin reader thread (4158/4158): blocked in read() — alive and waiting, so keys reach the process.
perry-signal-wake thread: alive.
tokio-rt-worker: present in only 924/4158 samples — the async runtime's worker was absent for ~78% of the window. The API socket is ESTABLISHED (request sent, response owed) but nothing pumps it.
kqueues show count=0; fds normal; one live TLS connection to the API.
So: timer wheel says nothing is due (a setInterval spinner at 1s cadence frozen ⇒ the due-check answers wrongly or the wheel lost the timer), stdin notifications don't reach dispatch, and tokio's events don't either. Producers and the loop header have become disconnected — the loop's liveness sees enough to keep parking-and-waking but its dispatch arms never fire.
Timer wheel state after heavy async churn — the freeze began mid-request after a big paste; a corrupted earliest-deadline (huge value) silences all timers while clock_gettime checks keep happening.
Tokio runtime starvation/death — if the worker exited or deadlocked, network completion never posts; but that alone doesn't explain frozen timers and dead input, so it may be downstream of 1.
Evidence bundle
/Users/amlug/projects/perry/wedge-9590/: wedge_sample.txt (full thread stacks, unsymbolized — binary stripped), lsof.txt, ps.txt, sbs_ram.log (memory timeline incl. the wedge window). Load address 0x1047f8000; hot frame offsets in the sample (kevent caller at +0xbcb8408, etc.) — a PERRY_KEEP_SYMBOLS=1 rebuild of the same SHA is needed to name them (note: the symbols build links a separate archive, so verify offsets against the symbolized binary's own sample, don't map across).
Repro direction
Not yet reduced. The trigger window: authenticated session, large pasted text, then a question whose response streams. A PTY driver replaying that shape against a symbolized build, sampled the moment the spinner stalls, is the path. The milder self-draining variant may reproduce more easily and share the root.
Severity: highest of the open TUI issues — a hard hang losing the session (work in the input box unrecoverable; transcript survives up to the wedge).
Live-captured from a wedged real session (macOS aarch64, main
8d27f7b964build, ~17 min into authenticated use). The most severe TUI defect observed: total dispatch stop while every component looks alive.The user-visible sequence
Long conversation → large paste → question submitted → response spinner (
Transmuting… (43s)) → counter freezes at 43s → all input dead (typing, ESC, Ctrl-C — nothing echoes or interrupts; raw mode, so Ctrl-C is an in-app byte, not a signal) → stays wedged indefinitely (>10 min). Memory flat at 680 MB throughout (no allocation → not processing).An earlier, milder sighting in the same session (#9587): multi-second freeze during busy work that then batch-drained on its own. This one never drained. Likely the same defect at different severities; keypress explicitly did NOT unstick either (that hypothesis is dead).
The forensics (5s
sample, all preserved)kevent(3988 in the syscall) +clock_gettimebursts — the loop parks, wakes, checks deadlines, re-parks. It is not stuck; it dispatches nothing.read()— alive and waiting, so keys reach the process.ESTABLISHED(request sent, response owed) but nothing pumps it.count=0; fds normal; one live TLS connection to the API.So: timer wheel says nothing is due (a
setIntervalspinner at 1s cadence frozen ⇒ the due-check answers wrongly or the wheel lost the timer), stdin notifications don't reach dispatch, and tokio's events don't either. Producers and the loop header have become disconnected — the loop's liveness sees enough to keep parking-and-waking but its dispatch arms never fire.Suspects, in order
event_loop.body_check/ sharedemit_event_loop_liveness) — the loop emission changed recently; a path where the re-check consults different state than the dispatch arms would produce exactly "wakes but never dispatches". The stdin-only programs exit before entering the event loop (40-60% of runs) #9416 two-copies trampoline (stdlib-vs-runtime predicate split) is the precedent for one side consulting a disconnected copy.clock_gettimechecks keep happening.Evidence bundle
/Users/amlug/projects/perry/wedge-9590/:wedge_sample.txt(full thread stacks, unsymbolized — binary stripped),lsof.txt,ps.txt,sbs_ram.log(memory timeline incl. the wedge window). Load address0x1047f8000; hot frame offsets in the sample (kevent caller at+0xbcb8408, etc.) — aPERRY_KEEP_SYMBOLS=1rebuild of the same SHA is needed to name them (note: the symbols build links a separate archive, so verify offsets against the symbolized binary's own sample, don't map across).Repro direction
Not yet reduced. The trigger window: authenticated session, large pasted text, then a question whose response streams. A PTY driver replaying that shape against a symbolized build, sampled the moment the spinner stalls, is the path. The milder self-draining variant may reproduce more easily and share the root.
Severity: highest of the open TUI issues — a hard hang losing the session (work in the input box unrecoverable; transcript survives up to the wedge).