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
{{ message }}
Repository navigation
Flaky under parallel load: a command typed right after Ctrl+C on a waiting read can fail to run #436
While verifying #426 (draft #433), one of 16 parallel copies of tests/inputOwnershipLive.test.ts (4 at a time, macOS 27, M2, 8 GB, load 3–6) failed:
live zsh: a command typed right after a read returns, or right after Ctrl+C, reaches the shell once, in order → timed out waiting for the command after Ctrl+C to run
The test runs read -r reply, waits 600 ms, sends Ctrl+C, types echo Y >> <marker> at 20 ms per key and presses Enter, then waits up to 15 s for that command's record.
Not reproduced
18/18 targeted runs on the #433 branch (12 of them 4× in parallel, load up to 16) and 18/18 on deva8b383c2. #433 does not touch this path: typing within 2 s of Ctrl+C is type-ahead (justStopped) and never held for a look.
Possible mechanism (unconfirmed)
Right after Ctrl+C, Enter sends the composer line straight to the PTY while the interrupted command is still formally running (toProgram when justStopped()). If the shell has not yet acted on SIGINT when that line arrives, the still-waiting read can take it as its answer, so the line never runs as a command. A real terminal has the same race for type-ahead; NMSh could instead hold that Enter until the prompt marker returns (bounded), which would also make the test deterministic.
To do
Reproduce with the queue entries and the shell's received input recorded before changing behavior. Related: #426, #356.
Reproduced and explained; fix in draft #437 (part of #431). The guess in the issue (the read taking the line) was wrong.
An instrumented copy of the test (8 at a time, load ~30, never committed) reproduced it on unmodified dev: the command that ran was the typed line with its beginning missing (olumes/…/once, cho Y >> …, exit 127). A frontend log of every input-state change and hand-over showed two mechanisms:
A late report of the question Ctrl+C ended (sampled before the interrupt) re-marked the post-Ctrl+C type-ahead as a reply; the prompt then discarded it mid-typing.
The shell's own prompt hooks read as the command waiting. After any command, zsh/Bash run their prompt hooks before the prompt marker; a slow hook holds the terminal, idle, like a builtin read. This needs neither Ctrl+C nor load: a slow prompt hook of the person's reproduces it at load 3.
Fix: stale pre-stop requests are dropped in the frontend, and each shell's first prompt hook prints an authenticated done marker after which the watch samples nothing until the next command. Regressions fail on dev and pass on the branch; full npm run verify green. Limits (zsh's single precmd function and Fish's other postexec handlers run before the marker; a tiny read-ordering window remains) are in the PR. This does not claim the whole input-race family is solved; keeping the issue open for physical QA.
v0.22 post-QA status (candidate fa7ec665). Physical QA A10 (prompt hooks and Ctrl+C, Ghostty + zsh) passed on 68c1cbb7. The Fish and Bash passes (B10, C10) were not run.
Both explained mechanisms stay fixed. On the integrated candidate: ctrlCTypeAhead (deterministic), promptHookLive 2/2 (zsh, Bash), typingAfterRead 3/3 (zsh, Bash, Fish) and inputOwnershipLive 6/6 all pass; CI green.
Remaining, as documented: zsh's single precmd function and Fish's other fish_postexec handlers run before NMSh's done marker, so a slow hook there can still be read as the command waiting. Not changed for v0.22: running NMSh's marker before a person's own precmd would mean renaming their function. The wider race family isn't declared solved; keeping this open.
Reassessed with #457 (e8dd44e4). The shell's done marker now reaches windows in the input state. A command typed and entered during a slow prompt hook, after the command was reported done, runs once at the verified prompt. A new live test covers zsh and Bash. Lines typed right after Ctrl+C are held until the prompt is verified, instead of being written while the stopped command still owns the terminal. If the program survives the stop, the line goes to it. Remaining, now a display limit only: zsh's single precmd and Fish's other fish_postexec handlers run before the done marker, so a slow hook there can still read as "waiting for input". Typing during it is held or taken back, never run. Open for physical QA (R6).
Activity
v0.22: physical QA checklist for #433 and #434; ledger links #436
raiseCatError commentedon Oct 18, 2026
Reproduced and explained; fix in draft #437 (part of #431). The guess in the issue (the
readtaking the line) was wrong.An instrumented copy of the test (8 at a time, load ~30, never committed) reproduced it on unmodified
dev: the command that ran was the typed line with its beginning missing (olumes/…/once,cho Y >> …, exit 127). A frontend log of every input-state change and hand-over showed two mechanisms:read. This needs neither Ctrl+C nor load: a slow prompt hook of the person's reproduces it at load 3.Fix: stale pre-stop requests are dropped in the frontend, and each shell's first prompt hook prints an authenticated
donemarker after which the watch samples nothing until the next command. Regressions fail ondevand pass on the branch; fullnpm run verifygreen. Limits (zsh's singleprecmdfunction and Fish's other postexec handlers run before the marker; a tiny read-ordering window remains) are in the PR. This does not claim the whole input-race family is solved; keeping the issue open for physical QA.Input ownership: a stale question is ignored only while typing is typ…
v0.22 docs: record D1-D3 decisions, PRs #437-#441, #436 findings and …
Merge #433 (input ownership look) into the #436 fix
raiseCatError commentedon Oct 19, 2026
v0.22 post-QA status (candidate
fa7ec665). Physical QA A10 (prompt hooks and Ctrl+C, Ghostty + zsh) passed on68c1cbb7. The Fish and Bash passes (B10, C10) were not run.Both explained mechanisms stay fixed. On the integrated candidate:
ctrlCTypeAhead(deterministic),promptHookLive2/2 (zsh, Bash),typingAfterRead3/3 (zsh, Bash, Fish) andinputOwnershipLive6/6 all pass; CI green.Remaining, as documented: zsh's single
precmdfunction and Fish's otherfish_postexechandlers run before NMSh's done marker, so a slow hook there can still be read as the command waiting. Not changed for v0.22: running NMSh's marker before a person's ownprecmdwould mean renaming their function. The wider race family isn't declared solved; keeping this open.Input ownership: a line begun after the shell said done is type-ahead…
Input ownership: a late report of the question just answered never ta…
raiseCatError commentedon Oct 19, 2026
Reassessed with #457 (
e8dd44e4). The shell's done marker now reaches windows in the input state. A command typed and entered during a slow prompt hook, after the command was reported done, runs once at the verified prompt. A new live test covers zsh and Bash. Lines typed right after Ctrl+C are held until the prompt is verified, instead of being written while the stopped command still owns the terminal. If the program survives the stop, the line goes to it. Remaining, now a display limit only: zsh's singleprecmdand Fish's otherfish_postexechandlers run before the done marker, so a slow hook there can still read as "waiting for input". Typing during it is held or taken back, never run. Open for physical QA (R6).