diff --git a/src/Command.zig b/src/Command.zig index 2801def36..6e30eae13 100644 --- a/src/Command.zig +++ b/src/Command.zig @@ -176,13 +176,13 @@ fn startPosix(self: *Command, arena: Allocator) !void { // We don't log because that'll show up in the output. }; + // Restore any rlimits that were set by Ghostty. This might fail but + // any failures are ignored (its best effort). + global_state.rlimits.restore(); + // If the user requested a pre exec callback, call it now. if (self.pre_exec) |f| f(self); - if (global_state.rlimits.nofile) |lim| { - internal_os.restoreMaxFiles(lim); - } - // Finally, replace our process. _ = posix.execveZ(pathZ, argsZ, envp) catch null; diff --git a/src/global.zig b/src/global.zig index b3f35fde5..c00ce27a4 100644 --- a/src/global.zig +++ b/src/global.zig @@ -27,12 +27,7 @@ pub const GlobalState = struct { alloc: std.mem.Allocator, action: ?cli.Action, logging: Logging, - /// If we change any resource limits for our own purposes, we save the - /// old limits so that they can be restored before we execute any child - /// processes. - rlimits: struct { - nofile: ?internal_os.rlimit = null, - } = .{}, + rlimits: ResourceLimits = .{}, /// The app resources directory, equivalent to zig-out/share when we build /// from source. This is null if we can't detect it. @@ -130,8 +125,8 @@ pub const GlobalState = struct { std.log.info("renderer={}", .{renderer.Renderer}); std.log.info("libxev backend={}", .{xev.backend}); - // First things first, we fix our file descriptors - self.rlimits.nofile = internal_os.fixMaxFiles(); + // As early as possible, initialize our resource limits. + self.rlimits = ResourceLimits.init(); // Initialize our crash reporting. crash.init(self.alloc) catch |err| { @@ -181,3 +176,21 @@ pub const GlobalState = struct { } } }; + +/// Maintains the Unix resource limits that we set for our process. This +/// can be used to restore the limits to their original values. +pub const ResourceLimits = struct { + nofile: ?internal_os.rlimit = null, + + pub fn init() ResourceLimits { + return .{ + // Maximize the number of file descriptors we can have open + // because we can consume a lot of them if we make many terminals. + .nofile = internal_os.fixMaxFiles(), + }; + } + + pub fn restore(self: *const ResourceLimits) void { + if (self.nofile) |lim| internal_os.restoreMaxFiles(lim); + } +}; diff --git a/src/os/file.zig b/src/os/file.zig index d89c05e3e..875dd2c25 100644 --- a/src/os/file.zig +++ b/src/os/file.zig @@ -23,9 +23,8 @@ pub fn fixMaxFiles() ?rlimit { return old; } - var lim = old; - // Do a binary search for the limit. + var lim = old; var min: posix.rlim_t = lim.cur; var max: posix.rlim_t = 1 << 20; // But if there's a defined upper bound, don't search, just set it.