gtk: convert cgroup operations to gobject (#6009)

This commit is contained in:
Jeffrey C. Ollie
2025-02-26 18:28:53 -06:00
committed by GitHub

View File

@ -2,8 +2,12 @@
/// each individual surface into its own cgroup. /// each individual surface into its own cgroup.
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
const gio = @import("gio");
const glib = @import("glib");
const gobject = @import("gobject");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const c = @import("c.zig").c;
const App = @import("App.zig"); const App = @import("App.zig");
const internal_os = @import("../../os/main.zig"); const internal_os = @import("../../os/main.zig");
@ -15,8 +19,6 @@ const log = std.log.scoped(.gtk_systemd_cgroup);
pub fn init(app: *App) ![]const u8 { pub fn init(app: *App) ![]const u8 {
const pid = std.os.linux.getpid(); const pid = std.os.linux.getpid();
const alloc = app.core_app.alloc; const alloc = app.core_app.alloc;
const connection = c.g_application_get_dbus_connection(@ptrCast(app.app)) orelse
return error.DbusConnectionRequired;
// Get our initial cgroup. We need this so we can compare // Get our initial cgroup. We need this so we can compare
// and detect when we've switched to our transient group. // and detect when we've switched to our transient group.
@ -29,7 +31,7 @@ pub fn init(app: *App) ![]const u8 {
// Create our transient scope. If this succeeds then the unit // Create our transient scope. If this succeeds then the unit
// was created, but we may not have moved into it yet, so we need // was created, but we may not have moved into it yet, so we need
// to do a dumb busy loop to wait for the move to complete. // to do a dumb busy loop to wait for the move to complete.
try createScope(connection); try createScope(app, pid);
const transient = transient: while (true) { const transient = transient: while (true) {
const current = try internal_os.cgroup.current( const current = try internal_os.cgroup.current(
alloc, alloc,
@ -110,9 +112,13 @@ fn enableControllers(alloc: Allocator, cgroup: []const u8) !void {
/// ///
/// On success this will return the name of the transient scope /// On success this will return the name of the transient scope
/// cgroup prefix, allocated with the given allocator. /// cgroup prefix, allocated with the given allocator.
fn createScope(connection: *c.GDBusConnection) !void { fn createScope(app: *App, pid_: std.os.linux.pid_t) !void {
// Our pid that we will move into the cgroup // FIXME: when app.app gets converted to gobject
const pid: c.guint32 = @intCast(std.os.linux.getpid()); const g_app: *gio.Application = @ptrCast(@alignCast(app.app));
const connection = g_app.getDbusConnection() orelse
return error.DbusConnectionRequired;
const pid: u32 = @intCast(pid_);
// The unit name needs to be unique. We use the pid for this. // The unit name needs to be unique. We use the pid for this.
var name_buf: [256]u8 = undefined; var name_buf: [256]u8 = undefined;
@ -122,70 +128,79 @@ fn createScope(connection: *c.GDBusConnection) !void {
.{pid}, .{pid},
) catch unreachable; ) catch unreachable;
const builder_type = glib.VariantType.new("(ssa(sv)a(sa(sv)))");
defer glib.free(builder_type);
// Initialize our builder to build up our parameters // Initialize our builder to build up our parameters
var builder: c.GVariantBuilder = undefined; var builder: glib.VariantBuilder = undefined;
c.g_variant_builder_init(&builder, c.G_VARIANT_TYPE("(ssa(sv)a(sa(sv)))")); builder.init(builder_type);
c.g_variant_builder_add(&builder, "s", name.ptr);
c.g_variant_builder_add(&builder, "s", "fail"); builder.add("s", name.ptr);
builder.add("s", "fail");
{ {
// Properties // Properties
c.g_variant_builder_open(&builder, c.G_VARIANT_TYPE("a(sv)")); const properties_type = glib.VariantType.new("a(sv)");
defer c.g_variant_builder_close(&builder); defer glib.free(properties_type);
builder.open(properties_type);
defer builder.close();
// https://www.freedesktop.org/software/systemd/man/latest/systemd-oomd.service.html // https://www.freedesktop.org/software/systemd/man/latest/systemd-oomd.service.html
c.g_variant_builder_add( const pressure_value = glib.Variant.newString("kill");
&builder,
"(sv)", builder.add("(sv)", "ManagedOOMMemoryPressure", pressure_value);
"ManagedOOMMemoryPressure",
c.g_variant_new_string("kill"),
);
// Delegate // Delegate
c.g_variant_builder_add( const delegate_value = glib.Variant.newBoolean(1);
&builder, builder.add("(sv)", "Delegate", delegate_value);
"(sv)",
"Delegate",
c.g_variant_new_boolean(1),
);
// Pid to move into the unit // Pid to move into the unit
c.g_variant_builder_add( const pids_value_type = glib.VariantType.new("u");
&builder, defer glib.free(pids_value_type);
"(sv)",
"PIDs", const pids_value = glib.Variant.newFixedArray(pids_value_type, &pid, 1, @sizeOf(u32));
c.g_variant_new_fixed_array(
c.G_VARIANT_TYPE("u"), builder.add("(sv)", "PIDs", pids_value);
&pid,
1,
@sizeOf(c.guint32),
),
);
}
{
// Aux
c.g_variant_builder_open(&builder, c.G_VARIANT_TYPE("a(sa(sv))"));
defer c.g_variant_builder_close(&builder);
} }
var err: ?*c.GError = null; {
defer if (err) |e| c.g_error_free(e); // Aux
_ = c.g_dbus_connection_call_sync( const aux_type = glib.VariantType.new("a(sa(sv))");
connection, defer glib.free(aux_type);
builder.open(aux_type);
defer builder.close();
}
var err: ?*glib.Error = null;
defer if (err) |e| e.free();
const reply_type = glib.VariantType.new("(o)");
defer glib.free(reply_type);
const value = builder.end();
const reply = connection.callSync(
"org.freedesktop.systemd1", "org.freedesktop.systemd1",
"/org/freedesktop/systemd1", "/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager", "org.freedesktop.systemd1.Manager",
"StartTransientUnit", "StartTransientUnit",
c.g_variant_builder_end(&builder), value,
c.G_VARIANT_TYPE("(o)"), reply_type,
c.G_DBUS_CALL_FLAGS_NONE, .{},
-1, -1,
null, null,
&err, &err,
) orelse { ) orelse {
if (err) |e| log.err( if (err) |e| log.err(
"creating transient cgroup scope failed code={} err={s}", "creating transient cgroup scope failed code={} err={s}",
.{ e.code, e.message }, .{
e.f_code,
if (e.f_message) |msg| msg else "(no message)",
},
); );
return error.DbusCallFailed; return error.DbusCallFailed;
}; };
defer reply.unref();
} }