termio: use a union to represent how a process is started

This commit is contained in:
Mitchell Hashimoto
2025-10-18 14:46:18 -07:00
parent df16c8f8a6
commit 7ec7dd7151

View File

@@ -102,24 +102,17 @@ pub fn threadEnter(
errdefer self.subprocess.stop();
// Watcher to detect subprocess exit
var process: ?xev.Process = process: {
var process: ?xev.Process = if (self.subprocess.process) |v| switch (v) {
.fork_exec => |cmd| try xev.Process.init(
cmd.pid orelse return error.ProcessNoPid,
),
// If we're executing via Flatpak then we can't do
// traditional process watching (its implemented
// as a special case in os/flatpak.zig) since the
// command is on the host.
if (comptime build_config.flatpak) {
if (self.subprocess.flatpak_command != null) {
break :process null;
}
}
// Get the pid from the subprocess
const command = self.subprocess.command orelse
return error.ProcessNotStarted;
const pid = command.pid orelse
return error.ProcessNoPid;
break :process try xev.Process.init(pid);
};
.flatpak => null,
} else return error.ProcessNotStarted;
errdefer if (process) |*p| p.deinit();
// Track our process start time for abnormal exits
@@ -167,17 +160,19 @@ pub fn threadEnter(
termio.Termio.ThreadData,
td,
processExit,
) else if (comptime build_config.flatpak) {
// If we're in flatpak and we have a flatpak command
// then we can run the special flatpak logic for watching.
if (self.subprocess.flatpak_command) |*c| {
c.waitXev(
) else if (comptime build_config.flatpak) flatpak: {
switch (self.subprocess.process orelse break :flatpak) {
// If we're in flatpak and we have a flatpak command
// then we can run the special flatpak logic for watching.
.flatpak => |*c| c.waitXev(
td.loop,
&td.backend.exec.flatpak_wait_c,
termio.Termio.ThreadData,
td,
flatpakExit,
);
),
.fork_exec => {},
}
}
@@ -587,10 +582,18 @@ const Subprocess = struct {
grid_size: renderer.GridSize,
screen_size: renderer.ScreenSize,
pty: ?Pty = null,
command: ?Command = null,
flatpak_command: ?FlatpakHostCommand = null,
process: ?Process = null,
linux_cgroup: Command.LinuxCgroup = Command.linux_cgroup_default,
/// Union that represents the running process type.
const Process = union(enum) {
/// Standard POSIX fork/exec
fork_exec: Command,
/// Flatpak DBus command
flatpak: FlatpakHostCommand,
};
const ArgsFormatter = struct {
args: []const [:0]const u8,
@@ -883,7 +886,7 @@ const Subprocess = struct {
read: Pty.Fd,
write: Pty.Fd,
} {
assert(self.pty == null and self.command == null);
assert(self.pty == null and self.process == null);
// This function is funny because on POSIX systems it can
// fail in the forked process. This is flipped to true if
@@ -959,15 +962,15 @@ const Subprocess = struct {
}
// Flatpak command must have a stable pointer.
self.flatpak_command = .{
self.process = .{ .flatpak = .{
.argv = self.args,
.cwd = cwd,
.env = if (self.env) |*env| env else null,
.stdin = pty.slave,
.stdout = pty.slave,
.stderr = pty.slave,
};
var cmd = &self.flatpak_command.?;
} };
var cmd = &self.process.?.flatpak;
const pid = try cmd.spawn(alloc);
errdefer killCommandFlatpak(cmd);
@@ -1046,7 +1049,7 @@ const Subprocess = struct {
self.env = null;
}
self.command = cmd;
self.process = .{ .fork_exec = cmd };
return switch (builtin.os.tag) {
.windows => .{
.read = pty.out_pipe,
@@ -1071,7 +1074,7 @@ const Subprocess = struct {
/// Called to notify that we exited externally so we can unset our
/// running state.
pub fn externalExit(self: *Subprocess) void {
self.command = null;
self.process = null;
}
/// Stop the subprocess. This is safe to call anytime. This will wait
@@ -1079,25 +1082,23 @@ const Subprocess = struct {
/// for it to terminate, so it will not block.
/// This does not close the pty.
pub fn stop(self: *Subprocess) void {
// Kill our command
if (self.command) |*cmd| {
// Note: this will also wait for the command to exit, so
// DO NOT call cmd.wait
killCommand(cmd) catch |err|
log.err("error sending SIGHUP to command, may hang: {}", .{err});
self.command = null;
}
switch (self.process orelse return) {
.fork_exec => |*cmd| {
// Note: this will also wait for the command to exit, so
// DO NOT call cmd.wait
killCommand(cmd) catch |err|
log.err("error sending SIGHUP to command, may hang: {}", .{err});
},
// Kill our Flatpak command
if (comptime build_config.flatpak) {
if (self.flatpak_command) |*cmd| {
.flatpak => |*cmd| if (comptime build_config.flatpak) {
killCommandFlatpak(cmd) catch |err|
log.err("error sending SIGHUP to command, may hang: {}", .{err});
_ = cmd.wait() catch |err|
log.err("error waiting for command to exit: {}", .{err});
self.flatpak_command = null;
}
},
}
self.process = null;
}
/// Resize the pty subprocess. This is safe to call anytime.