From 8d93016e923565e2e8b73aa7b549dd65b5d18a8c Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 15:02:31 -0300 Subject: Kill signals a command only while it runs, and only the pane it was meant for A signal effect carried only a slot, so a Kill followed in the same step by the pane's closing and its slot's reuse signalled the new pane's child; and a command pane whose child had exited and been reaped kept a process group id another process could take. The effect now carries the pane's serial, checked as it is performed, and a host signals no command whose exit it has recorded; the core already sends Kill only to a command it has not been told is done. Co-Authored-By: Claude Opus 5.5 --- src/tty/tty.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/tty') diff --git a/src/tty/tty.zig b/src/tty/tty.zig index 8e3809b0..14417cd0 100644 --- a/src/tty/tty.zig +++ b/src/tty/tty.zig @@ -1250,7 +1250,9 @@ const Shell = struct { fn ptySignal(ctx: ?*anyopaque, pane: u8, sig: pardes.PtySignal) void { const s = of(ctx); - if (s.ptys[pane]) |pt| host_io.signalTty(pt.pid, pt.file.handle, sig); + // A command whose exit is recorded is reaped: its group may be + // another's by now. + if (s.ptys[pane]) |pt| if (!pt.cmd.exited) host_io.signalTty(pt.pid, pt.file.handle, sig); } /// The pane is gone: hang its pty up, which the kernel passes on to the -- cgit v1.3