diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/apprt/gtk/pre_exec.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/apprt/gtk/pre_exec.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/apprt/gtk/pre_exec.zig | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/apprt/gtk/pre_exec.zig b/vendor/libghostty-vt/src/apprt/gtk/pre_exec.zig new file mode 100644 index 00000000..6f6a9ed5 --- /dev/null +++ b/vendor/libghostty-vt/src/apprt/gtk/pre_exec.zig @@ -0,0 +1,81 @@ +const std = @import("std"); + +const log = std.log.scoped(.gtk_pre_exec); + +const configpkg = @import("../../config.zig"); + +const internal_os = @import("../../os/main.zig"); +const Command = @import("../../Command.zig"); +const cgroup = @import("./cgroup.zig"); + +pub const PreExecInfo = struct { + gtk_single_instance: configpkg.Config.GtkSingleInstance, + linux_cgroup: configpkg.Config.LinuxCgroup, + linux_cgroup_hard_fail: bool, + + pub fn init(cfg: *const configpkg.Config) PreExecInfo { + return .{ + .gtk_single_instance = cfg.@"gtk-single-instance", + .linux_cgroup = cfg.@"linux-cgroup", + .linux_cgroup_hard_fail = cfg.@"linux-cgroup-hard-fail", + }; + } +}; + +/// If we are expecting to be moved to a transient systemd scope, wait to see if +/// that happens by checking for the correct name of the current cgroup. Wait at +/// most 250ms so that we don't overly delay the soft-fail scenario. +/// +/// If we are configured to hard fail, log an error message and return an error +/// code if we don't detect the move in time. +pub fn preExec(cmd: *Command) ?u8 { + switch (cmd.rt_pre_exec_info.linux_cgroup) { + .always => {}, + .never => return null, + .@"single-instance" => switch (cmd.rt_pre_exec_info.gtk_single_instance) { + .true => {}, + .false => return null, + .detect => { + log.err("gtk-single-instance is set to detect", .{}); + return 127; + }, + }, + } + + const pid: u32 = @intCast(std.os.linux.getpid()); + + var expected_cgroup_buf: [256]u8 = undefined; + const expected_cgroup = cgroup.fmtScope(&expected_cgroup_buf, pid); + + const start = std.time.Instant.now() catch unreachable; + + while (true) { + const now = std.time.Instant.now() catch unreachable; + + if (now.since(start) > 250 * std.time.ns_per_ms) { + if (cmd.rt_pre_exec_info.linux_cgroup_hard_fail) { + log.err("transition to new transient systemd scope took too long", .{}); + return 127; + } + break; + } + + not_found: { + var current_cgroup_buf: [4096]u8 = undefined; + + const current_cgroup_raw = internal_os.cgroup.current( + ¤t_cgroup_buf, + @intCast(pid), + ) orelse break :not_found; + + const index = std.mem.lastIndexOfScalar(u8, current_cgroup_raw, '/') orelse break :not_found; + const current_cgroup = current_cgroup_raw[index + 1 ..]; + + if (std.mem.eql(u8, current_cgroup, expected_cgroup)) return null; + } + + std.Thread.sleep(25 * std.time.ns_per_ms); + } + + return null; +} |
