mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
termio: on deinit, send SIGHUP to child process to exit it
This commit is contained in:
@ -15,6 +15,11 @@ const renderer = @import("../renderer.zig");
|
||||
|
||||
const log = std.log.scoped(.io_exec);
|
||||
|
||||
const c = @cImport({
|
||||
@cInclude("signal.h");
|
||||
@cInclude("unistd.h");
|
||||
});
|
||||
|
||||
/// Allocator
|
||||
alloc: Allocator,
|
||||
|
||||
@ -78,8 +83,8 @@ pub fn init(alloc: Allocator, opts: termio.Options) !Exec {
|
||||
.env = &env,
|
||||
.cwd = opts.config.@"working-directory",
|
||||
.pre_exec = (struct {
|
||||
fn callback(c: *Command) void {
|
||||
const p = c.getData(Pty) orelse unreachable;
|
||||
fn callback(cmd: *Command) void {
|
||||
const p = cmd.getData(Pty) orelse unreachable;
|
||||
p.childPreExec() catch |err|
|
||||
log.err("error initializing child: {}", .{err});
|
||||
}
|
||||
@ -113,9 +118,8 @@ pub fn init(alloc: Allocator, opts: termio.Options) !Exec {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Exec) void {
|
||||
// Deinitialize the pty. This closes the pty handles. This should
|
||||
// cause a close in the our subprocess so just wait for that.
|
||||
self.pty.deinit();
|
||||
// Kill our command
|
||||
self.killCommand();
|
||||
_ = self.command.wait() catch |err|
|
||||
log.err("error waiting for command to exit: {}", .{err});
|
||||
|
||||
@ -123,6 +127,22 @@ pub fn deinit(self: *Exec) void {
|
||||
self.terminal.deinit(self.alloc);
|
||||
}
|
||||
|
||||
/// Kill the underlying subprocess. This closes the pty file handle and
|
||||
/// sends a SIGHUP to the child process. This doesn't wait for the child
|
||||
/// process to be exited.
|
||||
fn killCommand(self: *Exec) void {
|
||||
// Close our PTY
|
||||
self.pty.deinit();
|
||||
|
||||
// We need to get our process group ID and send a SIGHUP to it.
|
||||
if (self.command.pid) |pid| {
|
||||
const pgid = c.getpgid(pid);
|
||||
if (pgid > 0) {
|
||||
_ = c.killpg(pgid, c.SIGHUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn threadEnter(self: *Exec, loop: libuv.Loop) !ThreadData {
|
||||
assert(self.data == null);
|
||||
|
||||
@ -367,15 +387,15 @@ fn ttyRead(t: *libuv.Tty, n: isize, buf: []const u8) void {
|
||||
var i: usize = 0;
|
||||
const end = @intCast(usize, n);
|
||||
if (ev.terminal_stream.parser.state == .ground) {
|
||||
for (buf[i..end]) |c| {
|
||||
switch (terminal.parse_table.table[c][@enumToInt(terminal.Parser.State.ground)].action) {
|
||||
for (buf[i..end]) |ch| {
|
||||
switch (terminal.parse_table.table[ch][@enumToInt(terminal.Parser.State.ground)].action) {
|
||||
// Print, call directly.
|
||||
.print => ev.terminal_stream.handler.print(@intCast(u21, c)) catch |err|
|
||||
.print => ev.terminal_stream.handler.print(@intCast(u21, ch)) catch |err|
|
||||
log.err("error processing terminal data: {}", .{err}),
|
||||
|
||||
// C0 execute, let our stream handle this one but otherwise
|
||||
// continue since we're guaranteed to be back in ground.
|
||||
.execute => ev.terminal_stream.execute(c) catch |err|
|
||||
.execute => ev.terminal_stream.execute(ch) catch |err|
|
||||
log.err("error processing terminal data: {}", .{err}),
|
||||
|
||||
// Otherwise, break out and go the slow path until we're
|
||||
@ -413,8 +433,8 @@ const StreamHandler = struct {
|
||||
try self.ev.queueWrite(data);
|
||||
}
|
||||
|
||||
pub fn print(self: *StreamHandler, c: u21) !void {
|
||||
try self.terminal.print(c);
|
||||
pub fn print(self: *StreamHandler, ch: u21) !void {
|
||||
try self.terminal.print(ch);
|
||||
}
|
||||
|
||||
pub fn bell(self: StreamHandler) !void {
|
||||
|
Reference in New Issue
Block a user