diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/tty/tty.zig | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/tty/tty.zig b/src/tty/tty.zig index ef7f2761..1d7ff415 100644 --- a/src/tty/tty.zig +++ b/src/tty/tty.zig @@ -1083,6 +1083,8 @@ pub fn run(init: std.process.Init, opts: pardes.Options, attach: ?[]const u8) !v defer vx.exitAltScreen(tty.writer()) catch {}; try vx.setMouseMode(tty.writer(), true); try vx.setBracketedPaste(tty.writer(), true); + Killed.arm(tty.fd.handle, tty.termios); + defer Killed.disarm(); if (attach != null) { attach_end = attachSession(init, attach_name, &tty, &vx); @@ -1119,6 +1121,40 @@ pub fn run(init: std.process.Init, opts: pardes.Options, attach: ?[]const u8) !v } } +/// SIGTERM or SIGHUP: the terminal put back as a clean exit leaves it -- +/// the main screen, no mouse, paste or keyboard modes, the cursor shown, +/// cooked termios -- and then the signal's own death. A nested editor +/// killed in a pane must not leave that pane's terminal wedged. +/// Async-signal-safe: write, tcsetattr, sigaction, raise. +const Killed = struct { + var fd: posix.fd_t = -1; + var cooked: posix.termios = undefined; + const reset = "\x1b[<u\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l\x1b[?1004l\x1b[?2004l\x1b[0m\x1b[?25h\x1b[?1049l"; + const signals = [_]posix.SIG{ .TERM, .HUP }; + + fn arm(tty_fd: posix.fd_t, termios: posix.termios) void { + cooked = termios; + fd = tty_fd; + const on: posix.Sigaction = .{ .handler = .{ .handler = handle }, .mask = posix.sigemptyset(), .flags = posix.SA.RESETHAND }; + for (signals) |sig| posix.sigaction(sig, &on, null); + } + + fn disarm() void { + fd = -1; + const default: posix.Sigaction = .{ .handler = .{ .handler = posix.SIG.DFL }, .mask = posix.sigemptyset(), .flags = 0 }; + for (signals) |sig| posix.sigaction(sig, &default, null); + } + + fn handle(sig: posix.SIG) callconv(.c) void { + if (fd >= 0) { + _ = std.c.write(fd, reset, reset.len); + _ = std.c.tcsetattr(fd, .FLUSH, &cooked); + } + // SA_RESETHAND put the default back: the same signal, now fatal. + _ = std.c.raise(sig); + } +}; + fn localSession( init: std.process.Init, opts: pardes.Options, |
