Skip to content

Fish integration: write a marker again once when the write fails (#443) - #445

Merged
raiseCatError merged 1 commit into
devfrom
fix/v022-fish-marker-retry
Oct 21, 2026
Merged

raiseCatError merged 1 commit into
devfrom
fix/v022-fish-marker-retry

Conversation

@raiseCatError

Copy link
Copy Markdown
Owner

Part of #443. Draft, for v0.22.0 (merged into release/v0.22.0, #444).

Problem. Fish 3 does not retry a terminal write that a signal interrupts. NMSh resizes the shell's terminal whenever its own rows change.

  • In Fish 3.7 on Linux: output and NMSh markers from Fish sometimes never reach NMSh (seen 3 times in CI) #443's trace, the write of one of NMSh's markers returned ERESTARTSYS on SIGWINCH, and Fish printed write: Interrupted system call.
  • A lost marker leaves NMSh wrong about whether a command runs.
  • From the code, a lost command-start marker would make NMSh treat a running program's prompt (sudo) as the idle shell. What is typed for it would then be drawn in the composer. The program still reads the line, so it is not recorded as a command, but it is visible.

Change. Fish's markers go through __nmsh_mark: printf with its error silenced, then once more if it failed.

Verified

Fish 3 does not retry a terminal write that a signal interrupts. NMSh
resizes the shell's terminal when its own rows change, so a marker
written while that write waits can be lost (#443's strace: the marker's
write returned ERESTARTSYS on SIGWINCH and Fish printed "write:
Interrupted system call"). A lost marker leaves NMSh wrong about whether
a command runs; a lost command-start marker would make it treat a
running program's prompt as the idle shell, and draw what is typed for
it in the composer.

Markers now go through __nmsh_mark: printf with its error silenced,
then once more if it failed. Output from the person's own commands is
unchanged and can still be lost this way (documented, #443).
raiseCatError added a commit that referenced this pull request Oct 19, 2026
…one streamlined QA walkthrough

- CHANGELOG: the #426 security entry includes the gate fixes (Tab
  replays text only; a password typed before the prompt is held, never
  sent or run; queued entries wait for approval on any question). The
  input limitations are listed case by case (a reply to a read NMSh has
  not seen, input entered before any question, hidden input, history,
  prompt hooks), and #443 states the lost write, its consequences, the
  affected environment and #445's marker retry.
- docs/testing/v022-physical-qa.md: one walkthrough in four sittings
  (Ghostty zsh in full; Terminal.app Fish, Terminal.app zsh and Bash,
  and Zed for what depends on the terminal or shell), each pass with
  commands, expectations, PASS/FAIL, reset and evidence; a build check
  before testing and a memory check before the local model.
- scripts/qa/v022-fixtures.sh: input/delayed-prompt.sh (as sudo does).
- Ledger: the gate review and its findings.
raiseCatError added a commit that referenced this pull request Oct 19, 2026
…d write never loses one (#443)

The fault-injection test (f909e77) failed on CI's Ubuntu Fish 3.7.0 as
expected for two interruptions in a row, and showed more: even when #445's
single retry saved the marker, Fish 3 printed "write: Interrupted system
call" into the transcript. Fish 3 reports a failed builtin write from its
own output layer on its own stderr, so the builtin's 2>/dev/null never
silenced it (#443's strace shows the same).

On Fish 3 a marker is now printf'd into a pipe (a few bytes, never
blocked, so never interrupted) and written to the terminal by cat, which
ignores SIGWINCH and retries an interrupted write. The marker travels on
stdin, never in arguments. Fish 4 retries by itself and keeps the builtin.
The cost is one short cat per marker, on Fish 3 only.

The test now runs Fish in a real terminal and fails only terminal writes,
as the real signal does (a pipe write of a few bytes never waits). A
characterisation test runs #445's helper under the same faults: on Fish 3
it shows the error and loses a marker interrupted twice. Command output
from Fish's own builtins is still lost on Fish 3 (the shim test documents
it); NMSh cannot retry a person's command for them.
@raiseCatError

Copy link
Copy Markdown
Owner Author

Merged into release/v0.22.0 earlier (d9d72a0c). On Fish 3 it's superseded by #449: a fault-injection test showed the single retry still printed write: Interrupted system call into the transcript and lost a marker interrupted twice. Fish 3 markers now go through cat. This helper remains the Fish 4 path (where Fish itself retries). Details on #443.

@raiseCatError

Copy link
Copy Markdown
Owner Author

#457 doesn't change this helper (the Fish 4 path). On Fish 3, markers still go through cat (#449), and NMSh's own layout no longer resizes the terminal (#443).

@raiseCatError
raiseCatError merged commit d9d72a0 into dev Oct 21, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant