# G-039 Investigate the orphaned-shell one-core spin on a dead console Status: proposed Scope: src/modules/punk/repl-999999.0a1.0.tm (console reader/event loop and EOF/error paths), src/modules/punk/console-999999.0a1.0.tm; investigation-first Goal: the observed failure mode - an interactive punk902z left running after its hosting terminal/console went away spins roughly a full core indefinitely (observed 2026-07-08: a 37-minute orphan with a single hard-looping thread) - is reliably reproduced and root-caused, then fixed or mitigated so a shell whose console dies exits or reaches zero-CPU idle cleanly. Acceptance: a documented procedure reproduces the spin on the current kit (e.g. launch an interactive shell in a terminal, then kill/close the hosting terminal or conhost), or the investigation records the attempts made and what evidence would reopen it; the spinning code path is identified (prime suspect: a console read/event loop treating a dead console's immediate EOF/error as retryable without backoff or termination - adjacent to the console-EOF restart path G-038 takes ownership of); after fix/mitigation, the same procedure shows the orphaned process exiting or settling at effectively zero CPU within a short grace period, with live-console interactive behaviour unchanged; the wedge-scoring hazard note (orphans polluting process-liveness checks in test harnesses) is updated to match the outcome. ## Context Observation (2026-07-08, during the G-036 investigation): a punk902z process from an earlier interactive session (started ~37 minutes prior; its hosting terminal presumed closed) was found consuming CPU continuously - ~1550 CPU-seconds accumulating at roughly +0.5-1 core-seconds per wall second, with exactly ONE thread in Running state (1546s of the total) and every other thread idle in normal waits. The process had to be killed manually. It also polluted the wedge-scoring checks of the day (process-liveness was being used as a hang signal), which is how it was noticed. Not diagnosed at the time (killed to unblock the G-036 work); no dump was taken. The suspicion: when the hosting console goes away, a console channel read/event path returns immediately (EOF or error) and the surrounding loop retries without backoff or a give-up-and-exit decision. Candidate sites: the repl reader loop, the EOF branch behaviour when reopen/restart fails or loops (note tcl_interactive would be true for a real console, enabling the `after 1 reopen_stdin` path - see the race notes in the G-038 detail file), or punk::console query/read helpers. ## Approach 1. Reproduce: launch an interactive shell in a disposable terminal and kill the host (close the tab/window; `Stop-Process` on the terminal; for classic conhost, killing conhost.exe; also try Windows Terminal vs conhost - behaviour may differ). Watch the orphan's CPU and thread states (`(Get-Process punk902z).Threads` sorted by TotalProcessorTime). Try both idle-at-prompt and mid-command states at kill time. 2. If reproduced: procdump + WinDbgX scripted stack capture of the spinning thread (the G-036 detail file documents the working tooling pipeline and pitfalls - WinDbgX process name is DbgX.Shell, cdb is ACL-buried, `-z/-p -c -logo` scripting works). With the spin thread's stack, map to the retry loop and decide fix: treat dead-console EOF/error as terminal (exit per PUNK_PIPE_EOF-like policy), or add backoff + detection. 3. Coordinate with G-038: its caller-driven restart owns the console-EOF path; the dead console case is the failure branch of the same decision point (reopen CONIN$ fails or the console is gone entirely) and should be designed together. ## Notes - Related: G-038 (console-EOF restart ownership, reopen_stdin race notes), G-036 (dump/ debugging tooling pipeline), tcl86-console-parked-read prior art (different mechanism, same neighbourhood). - Harness hygiene until fixed: verify no stray punk902z processes before scoring any liveness-based test run. - Archived-goal references in this file: G-036 achieved 2026-07-08 (goals/archive/G-036-tcl9-udp-console-worker-wedge.md).