Parent: #160.
The syntax-highlighting PR #174 exposed a pre-existing terminal disconnect bug.
The monitor polls stdin with events = 0; on macOS a direct PTY probe returns no hangup for that mask after the controller closes, while POLLIN returns POLLIN | POLLHUP.
The editor often exits later through a failed write, which masks the broken monitor until startup takes longer than the one-second test deadline.
Diagnostic logs confirmed the monitor was alive and repeatedly returned zero after controller closure.
A separate observed ttyname_r failure can also silently disable the guard; use descriptor device identity to exclude /dev/tty without name lookup.
Acceptance criteria:
- The monitor detects a direct macOS PTY controller disconnect independently of editor rendering or input dispatch.
- Keep the existing one-second exit requirement.
- Ordinary readable input is neither consumed by the monitor nor allowed to cause a busy loop.
- Redirected stdin and the special
/dev/tty descriptor retain their existing cleanup behavior.
- No test deadline increases, skips, or retries used to hide a failure.
Checks:
- Regression test with a real PTY proves the polling mask reports controller hangup and preserves unread input.
- Focused descriptor classification tests for real terminal,
/dev/tty, and non-terminal inputs.
- Terminal integration suite, formatting, Clippy, release build, and a real shell-restoration smoke check.
- Fresh review and required GitHub checks before merge.
Parent: #160.
The syntax-highlighting PR #174 exposed a pre-existing terminal disconnect bug.
The monitor polls stdin with
events = 0; on macOS a direct PTY probe returns no hangup for that mask after the controller closes, whilePOLLINreturnsPOLLIN | POLLHUP.The editor often exits later through a failed write, which masks the broken monitor until startup takes longer than the one-second test deadline.
Diagnostic logs confirmed the monitor was alive and repeatedly returned zero after controller closure.
A separate observed
ttyname_rfailure can also silently disable the guard; use descriptor device identity to exclude/dev/ttywithout name lookup.Acceptance criteria:
/dev/ttydescriptor retain their existing cleanup behavior.Checks:
/dev/tty, and non-terminal inputs.