From d351e801580e2271980ed6f33f5975f4b14d722c Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 4 Jun 2024 20:22:17 -0700 Subject: [PATCH] os: cgroup create/move --- src/apprt/gtk/cgroup.zig | 5 +++++ src/os/cgroup.zig | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/apprt/gtk/cgroup.zig b/src/apprt/gtk/cgroup.zig index ecee3f149..1b621d792 100644 --- a/src/apprt/gtk/cgroup.zig +++ b/src/apprt/gtk/cgroup.zig @@ -41,6 +41,11 @@ pub fn init(app: *App) ![]const u8 { errdefer alloc.free(transient); log.info("transient scope created cgroup={s}", .{transient}); + // Create the app cgroup and put ourselves in it. This is + // required because controllers can't be configured while a + // process is in a cgroup. + try internal_os.cgroup.create(transient, "app.scope", pid); + // Enable all of our cgroup controllers. If these fail then // we just log. We can't reasonably undo what we've done above // so we log the warning and still return the transient group. diff --git a/src/os/cgroup.zig b/src/os/cgroup.zig index 2f4f5d884..baad0c070 100644 --- a/src/os/cgroup.zig +++ b/src/os/cgroup.zig @@ -28,6 +28,30 @@ pub fn current(alloc: Allocator, pid: std.os.linux.pid_t) !?[]const u8 { return try alloc.dupe(u8, result); } +/// Create a new cgroup. This will not move any process into it unless move is +/// set. If move is set, the given pid will be moved into the created cgroup. +pub fn create( + cgroup: []const u8, + child: []const u8, + move: ?std.os.linux.pid_t, +) !void { + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + const path = try std.fmt.bufPrint(&buf, "/sys/fs/cgroup{s}/{s}", .{ cgroup, child }); + try std.fs.cwd().makePath(path); + + // If we have a PID to move into the cgroup immediately, do it. + if (move) |pid| { + const pid_path = try std.fmt.bufPrint( + &buf, + "/sys/fs/cgroup{s}/{s}/cgroup.procs", + .{ cgroup, child }, + ); + const file = try std.fs.cwd().openFile(pid_path, .{ .mode = .write_only }); + defer file.close(); + try file.writer().print("{}", .{pid}); + } +} + /// Returns all available cgroup controllers for the given cgroup. /// The cgroup should have a '/'-prefix. ///