summaryrefslogtreecommitdiff
path: root/src/host_io.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/host_io.zig')
-rw-r--r--src/host_io.zig25
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;