fix(tui): handle raw-mode startup EIO

This commit is contained in:
Mantas Vidutis
2026-08-03 12:05:47 -07:00
parent 5af71dc9cf
commit 46051126a3
2 changed files with 28 additions and 2 deletions
+9 -2
View File
@@ -717,10 +717,17 @@ export class ProcessTerminal implements Terminal {
// stderr-guard in pi-utils (mirrors openai/codex#24459).
suppressTerminalStderr();
// Save previous state and enable raw mode
// A multiplexer or SSH disconnect can leave isTTY true after its pty has
// been revoked. Raw mode is then impossible, so take the normal terminal
// disconnect path rather than letting Bun abort startup with EIO.
this.#wasRaw = process.stdin.isRaw || false;
if (process.stdin.setRawMode) {
process.stdin.setRawMode(true);
try {
process.stdin.setRawMode(true);
} catch (err) {
this.#markTerminalDisconnected("stdin raw mode setup failed", err);
return;
}
}
process.stdin.setEncoding("utf8");
process.stdin.on("end", this.#stdinEndHandler);
@@ -76,6 +76,25 @@ describe("ProcessTerminal disconnect with a revoked pty", () => {
expect(signals).toContain("SIGHUP");
});
it("treats an initial EIO enabling raw mode as a terminal disconnect", () => {
Object.defineProperty(process.stdin, "setRawMode", {
value: () => {
throw new Error("setRawMode failed with errno: 5");
},
configurable: true,
});
const terminal = new ProcessTerminal();
expect(() =>
terminal.start(
() => {},
() => {},
() => terminal.stop(),
),
).not.toThrow();
expect(signals).toContain("SIGHUP");
});
it("propagates a raw-mode restore failure while the terminal is still live", () => {
let started = false;
Object.defineProperty(process.stdin, "setRawMode", {