diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 52ab5af8a..6cda51475 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -44,6 +44,9 @@ config: Config, app: *c.GtkApplication, ctx: *c.GMainContext, +/// True if the app was launched with single instance mode. +single_instance: bool, + /// The "none" cursor. We use one that is shared across the entire app. cursor_none: ?*c.GdkCursor, @@ -269,6 +272,7 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { .ctx = ctx, .cursor_none = cursor_none, .x11_xkb = x11_xkb, + .single_instance = single_instance, // If we are NOT the primary instance, then we never want to run. // This means that another instance of the GTK app is running and // our "activate" call above will open a window. @@ -388,17 +392,25 @@ pub fn run(self: *App) !void { // If we are running, then we proceed to setup our app. // Setup our cgroup configurations for our surfaces. - if (cgroup.init(self)) |cgroup_path| { - self.transient_cgroup_base = cgroup_path; - } else |err| { - // If we can't initialize cgroups then that's okay. We - // want to continue to run so we just won't isolate surfaces. - // NOTE(mitchellh): do we want a config to force it? - log.warn( - "failed to initialize cgroups, terminals will not be isolated err={}", - .{err}, - ); - } + if (switch (self.config.@"linux-cgroup") { + .never => false, + .always => true, + .@"single-instance" => self.single_instance, + }) cgroup: { + const path = cgroup.init(self) catch |err| { + // If we can't initialize cgroups then that's okay. We + // want to continue to run so we just won't isolate surfaces. + // NOTE(mitchellh): do we want a config to force it? + log.warn( + "failed to initialize cgroups, terminals will not be isolated err={}", + .{err}, + ); + break :cgroup; + }; + + log.info("cgroup isolation enabled base={s}", .{path}); + self.transient_cgroup_base = path; + } else log.debug("cgroup isoation disabled config={}", .{self.config.@"linux-cgroup"}); // Setup our menu items self.initActions(); diff --git a/src/build/fish_completions.zig b/src/build/fish_completions.zig index b72360e7d..3a006a7b2 100644 --- a/src/build/fish_completions.zig +++ b/src/build/fish_completions.zig @@ -12,7 +12,7 @@ pub const fish_completions = comptimeGenerateFishCompletions(); fn comptimeGenerateFishCompletions() []const u8 { comptime { - @setEvalBranchQuota(13000); + @setEvalBranchQuota(15000); var counter = std.io.countingWriter(std.io.null_writer); try writeFishCompletions(&counter.writer()); diff --git a/src/config/Config.zig b/src/config/Config.zig index c17d1e42d..5b7370e37 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -988,6 +988,30 @@ keybind: Keybinds = .{}, /// This does not work with GLFW builds. @"macos-option-as-alt": OptionAsAlt = .false, +/// Put every surface (tab, split, window) into a dedicated Linux cgroup. +/// +/// This makes it so that resource management can be done on a per-surface +/// granularity. For example, if a shell program is using too much memory, +/// only that shell will be killed by the oom monitor instead of the entire +/// Ghostty process. Similarly, if a shell program is using too much CPU, +/// only that surface will be CPU-throttled. +/// +/// This will cause startup times to be slower (a hundred milliseconds or so), +/// so the default value is "single-instance." In single-instance mode, only +/// one instance of Ghostty is running (see gtk-single-instance) so the startup +/// time is a one-time cost. Additionally, single instance Ghostty is much +/// more likely to have many windows, tabs, etc. so cgroup isolation is a +/// big benefit. +/// +/// Valid values are: +/// +/// * `never` - Never use cgroups. +/// * `always` - Always use cgroups. +/// * `single-instance` - Enable cgroups only for Ghostty instances launched +/// as single-instance applications (see gtk-single-instance). +/// +@"linux-cgroup": LinuxCgroup = .@"single-instance", + /// If true, the Ghostty GTK application will run in single-instance mode: /// each new `ghostty` process launched will result in a new window if there /// is already a running process. @@ -3495,3 +3519,10 @@ pub const GraphemeWidthMethod = enum { legacy, unicode, }; + +/// See linux-cgroup +pub const LinuxCgroup = enum { + never, + always, + @"single-instance", +};