github / github/copilot-cli

TUI wedges mid-turn (screen clears, input dead, Ctrl+C/Ctrl+\ ignored) — write EIO on stdout followed by EPIPE on Rust JSON-RPC transport; WSL2 + Windows Terminal

Ouverte
#4,069 7 commentaires 9 réactions 0 personnes assignées Voir sur GitHub
area:input-keyboard area:terminal-rendering
Langage dominant
Shell
Étoiles
11.2k
Forks
1.9k
Merge moyen
14 h 16 min
PR mergées (30 j)
6

Description

# Copilot CLI — mid-turn screen clear / unresponsive terminal

## Environment

- CLI version: `1.0.70-0`
- Node: `v24.11.1`
- OS: WSL2 (Ubuntu) on Windows 11
- Terminal: Windows Terminal
- Model in use: `claude-opus-4.7`

## Symptom

While the assistant is actively working in a session (streaming a reply and/or
running tools mid-turn), the CLI's terminal pane suddenly:

1. Clears to a blank alternate-screen buffer (just a cursor at column 0)
2. Stops rendering any further output
3. Stops accepting input — typing does nothing
4. Ignores `Ctrl+C` **and** `Ctrl+\` (SIGQUIT)
5. The underlying `copilot` node process remains alive; only tab-close /
external `kill -9` from another shell (or a reboot) recovers the terminal

Not idle-related. Reproduced within ~10 minutes of a fresh boot, mid-turn.
Multiple sessions in the same day exhibited it.

## What is NOT happening

- Not caused by leaving the CLI idle (initially suspected, ruled out — happens
mid-turn during active streaming/tool use).
- Not a terminal resize (no SIGWINCH in the timeline).
- Not user-initiated shutdown (no `Ctrl+D`, no `/exit`, no window close).

## Log signature

Recent process logs under `~/.copilot/logs/` for wedged sessions contain this
pattern around the point of failure:

```
[DEBUG] Ignoring transient stdout error: write EIO
[DEBUG] Uncaught Exception (transient I/O, suppressed): write EPIPE
Error: write EPIPE
[ERROR] Rust JSON-RPC transport error: Error: write EPIPE
...
[DEBUG] [shutdown] Starting dispose: InkInstance.rerender
[DEBUG] Ignoring transient stdout error: write EIO
[DEBUG] [shutdown] Completed dispose: InkInstance.rerender (65ms)
```

The `write EIO` on stdout and `write EPIPE` on the Rust JSON-RPC transport
cluster together, then Ink attempts a shutdown re-render. This looks like the
Ink renderer (or something writing to stdout in parallel with it) hits EIO,
which then cascades EPIPE across the extension-host IPC pipes. Because the
CLI classifies EIO as "transient" and does not abort, the process keeps
running with a dead TTY — no input handler, no visible output.

Contributing hypothesis: high re-render rate during streaming
(`assistant.streaming_delta` + `assistant.tool_call_delta` events) combined
with concurrent writers to stdout produces a short window where a write races
with something (terminal state change? SIGWINCH from Windows Terminal?
extension-host handshake?) and stdout returns EIO. Once stdout is EIO, Ink
can no longer paint and the input reader also stalls.

## Wedged process observations

Example: PID 2160 (`copilot`, pts/2), state `Sl+`, still alive over an hour
after the wedge. Log
`~/.copilot/logs/process-1783606860101-2160.log` shows normal activity, then
only ExP telemetry heartbeats every ~10 minutes — no user input events, no
render updates. Consistent with "TUI/input loop dead, background workers
alive."

## Impact

- Loss of the active turn's visible output (state is still on disk under
`~/.copilot/session-state//` and resumable, but the in-progress reply
is gone).
- Ctrl+C / Ctrl+\ ineffective — no graceful shutdown path from within the
wedged terminal.
- Requires killing the process from a separate shell, or a system reboot in
the worst case.

## Requested fixes / improvements

1. When stdout returns `EIO` repeatedly (say, more than N times in M ms),
treat it as fatal instead of transient. Either:
- attempt to reopen `/dev/tty` and re-attach Ink, or
- exit cleanly with a diagnostic message.
2. Ensure `Ctrl+C` and `Ctrl+\` remain honored even if the Ink render loop
is stalled — the SIGINT/SIGQUIT handler should not depend on the TUI
being alive.
3. Optional: a `COPILOT_NO_ALT_SCREEN=1` / `--no-alt-screen` escape hatch
that renders inline instead of using the alternate screen buffer, so a
wedge doesn't hide scrollback and leaves recovery affordances visible.
4. Investigate whether the extension-host EPIPE bursts (link-checker,
stale-content-finder, pr-review-feedback, crlf-guard, frontmatter-validator,
ms-date-auto-updater are all forked at startup on this system) contribute
by writing to shared stdio pipes during a render.

Guide de contribution

Ouvrir le guide de contribution

Piste de recherche

Commencez par reproduire le mid-turn wedge dans WSL2 avec Windows Terminal tout en collectant le journal des processus de ~/.copilot/logs/, puis suivez la séquence de gestion de stdout EIO, de re-rendu lors de l'arrêt de Ink et de EPIPE de Rust JSON-RPC décrite ici. La tâche doit inclure un comportement défini de récupération ou de sortie propre, et Ctrl+C ainsi que Ctrl+\\ doivent rester effectifs lorsque le rendu est bloqué.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
node.js, rust
Domaine
cli
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Calme
Clarté
À clarifier
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.