diff options
Diffstat (limited to 'src/host_io.zig')
| -rw-r--r-- | src/host_io.zig | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/host_io.zig b/src/host_io.zig index a5efc7d1..5d9dd413 100644 --- a/src/host_io.zig +++ b/src/host_io.zig @@ -1337,8 +1337,14 @@ pub fn signalTty(shell_pid: libc.pid_t, master_fd: c_int, which: pardes.PtySigna .hup => libc.SIG.HUP, .quit => libc.SIG.QUIT, .kill => libc.SIG.KILL, + .command => libc.SIG.TERM, }; const fg = tcgetpgrp(master_fd); + // The shell leads its own group: a job it runs has another. + if (which == .command) { + if (fg > 0 and fg != shell_pid) _ = libc.kill(-fg, sig); + return; + } if (fg > 0) { _ = libc.kill(-fg, sig); return; @@ -1640,6 +1646,25 @@ test "an idle prompt is free, a foreground job takes the tty, and Ctrl-C hands i try std.testing.expect(sh.waitText(test_prompt, 10_000)); } +test "Kill's signal stops the foreground job and never the shell" { + if (comptime !tty_probe_platform) return error.SkipZigTest; + var sh = TestShell.start() orelse return error.SkipZigTest; + defer sh.stop(); + + // At the prompt the shell is the foreground: there is nothing to stop. + signalTty(sh.pid, sh.master, .command); + sleepMs(100); + try std.testing.expectEqual(@as(libc.pid_t, 0), libc.waitpid(sh.pid, null, libc.W.NOHANG)); + + sh.send("sleep 30\n"); + try std.testing.expect(sh.waitTaken(true, 10_000)); + sh.forget(); + signalTty(sh.pid, sh.master, .command); + try std.testing.expect(sh.waitTaken(false, 10_000)); + try std.testing.expect(sh.waitText(test_prompt, 10_000)); + try std.testing.expectEqual(@as(libc.pid_t, 0), libc.waitpid(sh.pid, null, libc.W.NOHANG)); +} + test "a background job is not the tty's owner" { if (comptime !tty_probe_platform) return error.SkipZigTest; var sh = TestShell.start() orelse return error.SkipZigTest; |
