plumb the linux cgroup through to termio

This commit is contained in:
Mitchell Hashimoto
2024-06-04 21:37:34 -07:00
parent 1285b4f243
commit dc51b8269c
4 changed files with 69 additions and 2 deletions

View File

@ -404,6 +404,16 @@ pub fn init(
.renderer_wakeup = render_thread.wakeup, .renderer_wakeup = render_thread.wakeup,
.renderer_mailbox = render_thread.mailbox, .renderer_mailbox = render_thread.mailbox,
.surface_mailbox = .{ .surface = self, .app = app_mailbox }, .surface_mailbox = .{ .surface = self, .app = app_mailbox },
// Get the cgroup if we're on linux and have the decl. I'd love
// to change this from a decl to a surface options struct because
// then we can do memory management better (don't need to retain
// the string around).
.linux_cgroup = if (comptime builtin.os.tag == .linux and
@hasDecl(apprt.runtime.Surface, "cgroup"))
rt_surface.cgroup()
else
termio.Options.linux_cgroup_default,
}); });
errdefer io.deinit(); errdefer io.deinit();

View File

@ -11,6 +11,7 @@ const font = @import("../../font/main.zig");
const input = @import("../../input.zig"); const input = @import("../../input.zig");
const terminal = @import("../../terminal/main.zig"); const terminal = @import("../../terminal/main.zig");
const CoreSurface = @import("../../Surface.zig"); const CoreSurface = @import("../../Surface.zig");
const internal_os = @import("../../os/main.zig");
const App = @import("App.zig"); const App = @import("App.zig");
const Split = @import("Split.zig"); const Split = @import("Split.zig");
@ -255,6 +256,10 @@ im_commit_buffered: bool = false,
im_buf: [128]u8 = undefined, im_buf: [128]u8 = undefined,
im_len: u7 = 0, im_len: u7 = 0,
/// The surface-specific cgroup path. See App.transient_cgroup_path for
/// details on what this is.
cgroup_path: ?[]const u8 = null,
pub fn create(alloc: Allocator, app: *App, opts: Options) !*Surface { pub fn create(alloc: Allocator, app: *App, opts: Options) !*Surface {
var surface = try alloc.create(Surface); var surface = try alloc.create(Surface);
errdefer alloc.destroy(surface); errdefer alloc.destroy(surface);
@ -342,6 +347,36 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
break :font_size parent.font_size; break :font_size parent.font_size;
}; };
// If the parent has a transient cgroup, then we're creating cgroups
// for each surface if we can. We need to create a child cgroup.
const cgroup_path: ?[]const u8 = cgroup: {
const base = app.transient_cgroup_base orelse break :cgroup null;
// For the unique group name we use the self pointer. This may
// not be a good idea for security reasons but not sure yet. We
// may want to change this to something else eventually to be safe.
var buf: [256]u8 = undefined;
const name = std.fmt.bufPrint(
&buf,
"surface({X}).scope",
.{@intFromPtr(self)},
) catch unreachable;
// Create the cgroup. If it fails, no big deal... just ignore.
internal_os.cgroup.create(base, name, null) catch |err| {
log.err("failed to create surface cgroup err={}", .{err});
break :cgroup null;
};
// Success, save the cgroup path.
break :cgroup std.fmt.allocPrint(
app.core_app.alloc,
"{s}/{s}",
.{ base, name },
) catch null;
};
errdefer if (cgroup_path) |path| app.core_app.alloc.free(path);
// Build our result // Build our result
self.* = .{ self.* = .{
.app = app, .app = app,
@ -354,6 +389,7 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
.size = .{ .width = 800, .height = 600 }, .size = .{ .width = 800, .height = 600 },
.cursor_pos = .{ .x = 0, .y = 0 }, .cursor_pos = .{ .x = 0, .y = 0 },
.im_context = im_context, .im_context = im_context,
.cgroup_path = cgroup_path,
}; };
errdefer self.* = undefined; errdefer self.* = undefined;
@ -442,9 +478,10 @@ pub fn deinit(self: *Surface) void {
self.core_surface.deinit(); self.core_surface.deinit();
self.core_surface = undefined; self.core_surface = undefined;
if (self.cgroup_path) |path| self.app.core_app.alloc.free(path);
// Free all our GTK stuff // Free all our GTK stuff
c.g_object_unref(self.im_context); c.g_object_unref(self.im_context);
if (self.cursor) |cursor| c.g_object_unref(cursor); if (self.cursor) |cursor| c.g_object_unref(cursor);
} }
@ -463,6 +500,11 @@ fn render(self: *Surface) !void {
try self.core_surface.renderer.drawFrame(self); try self.core_surface.renderer.drawFrame(self);
} }
/// Called by core surface to get the cgroup.
pub fn cgroup(self: *const Surface) ?[]const u8 {
return self.cgroup_path;
}
/// Queue the inspector to render if we have one. /// Queue the inspector to render if we have one.
pub fn queueInspectorRender(self: *Surface) void { pub fn queueInspectorRender(self: *Surface) void {
if (self.inspector) |v| v.queueRender(); if (self.inspector) |v| v.queueRender();

View File

@ -179,7 +179,14 @@ pub fn init(alloc: Allocator, opts: termio.Options) !Exec {
term.width_px = subprocess.screen_size.width; term.width_px = subprocess.screen_size.width;
term.height_px = subprocess.screen_size.height; term.height_px = subprocess.screen_size.height;
return Exec{ // TODO: make work
if (comptime builtin.os.tag == .linux) {
if (opts.linux_cgroup) |cgroup| {
log.warn("DESIRED cgroup={s}", .{cgroup});
}
}
return .{
.alloc = alloc, .alloc = alloc,
.terminal = term, .terminal = term,
.subprocess = subprocess, .subprocess = subprocess,

View File

@ -1,5 +1,6 @@
//! The options that are used to configure a terminal IO implementation. //! The options that are used to configure a terminal IO implementation.
const builtin = @import("builtin");
const xev = @import("xev"); const xev = @import("xev");
const apprt = @import("../apprt.zig"); const apprt = @import("../apprt.zig");
const renderer = @import("../renderer.zig"); const renderer = @import("../renderer.zig");
@ -41,3 +42,10 @@ renderer_mailbox: *renderer.Thread.Mailbox,
/// The mailbox for sending the surface messages. /// The mailbox for sending the surface messages.
surface_mailbox: apprt.surface.Mailbox, surface_mailbox: apprt.surface.Mailbox,
/// The cgroup to apply to the started termio process, if able by
/// the termio implementation. This only applies to Linux.
linux_cgroup: LinuxCgroup = linux_cgroup_default,
pub const LinuxCgroup = if (builtin.os.tag == .linux) ?[]const u8 else void;
pub const linux_cgroup_default = if (LinuxCgroup == void) {} else null;