Fix some memory leaks

This commit is contained in:
Ben Buhse 2026-02-22 17:38:28 -06:00
commit 8e6c28da7b
No known key found for this signature in database
GPG key ID: 7916ACFCD38FD0B4
7 changed files with 37 additions and 10 deletions

View file

@ -116,6 +116,13 @@ pub fn destroy(context: *Context) void {
if (context.tag_overlay_timer_fd) |fd| posix.close(fd);
context.buffer_pool.deinit();
// Destroy Wayland globals
context.river_layer_shell_v1.destroy();
context.zwlr_layer_shell_v1.destroy();
context.wl_shm.destroy();
context.wl_compositor.destroy();
context.wl_registry.destroy();
utils.gpa.destroy(context);
}

View file

@ -38,6 +38,8 @@ pub fn create(context: *Context, river_input_manager_v1: *river.InputManagerV1,
}
pub fn destroy(im: *InputManager) void {
im.river_input_manager_v1.destroy();
im.river_libinput_config_v1.destroy();
utils.gpa.destroy(im);
}

View file

@ -285,12 +285,13 @@ fn isSupported(comptime E: type, comptime S: type, val: E, support: S) bool {
/// log any unsupported or invalid config responses from the compositor.
fn applyResult(result: anyerror!*river.LibinputResultV1) void {
const Listener = struct {
fn resultListener(_: *river.LibinputResultV1, event: river.LibinputResultV1.Event, _: ?*anyopaque) void {
fn resultListener(libinput_result: *river.LibinputResultV1, event: river.LibinputResultV1.Event, _: ?*anyopaque) void {
switch (event) {
.success => {},
.unsupported => log.debug("Config option unsupported by device", .{}),
.invalid => log.warn("Invalid config value for device", .{}),
}
libinput_result.destroy();
}
};

View file

@ -118,20 +118,28 @@ pub fn create(context: *Context, river_output_v1: *river.OutputV1) !*Output {
}
pub fn destroy(output: *Output) void {
// Destroy any windows left on the Output
// This *should* be empty
var it = output.windows.safeIterator(.forward);
while (it.next()) |window| {
window.link.remove();
window.destroy();
}
// Deinit optional surfaces
if (output.bar) |*bar| bar.deinit();
if (output.tag_overlay) |*tag_overlay| tag_overlay.deinit();
output.tag_layout_overrides.deinit(utils.gpa);
output.deinitWallpaperLayerSurface();
if (output.wl_output) |wl_output| wl_output.release();
output.river_output_v1.destroy();
// Destroy/deinit other Output fields
output.tag_layout_overrides.deinit(utils.gpa);
if (output.name) |name| utils.gpa.free(name);
// Destroy/release relevant Wayland interfaces
output.river_layer_shell_output_v1.destroy();
output.river_output_v1.destroy();
if (output.wl_output) |wl_output| wl_output.release();
utils.gpa.destroy(output);
}
@ -302,6 +310,7 @@ fn wlOutputListener(_: *wl.Output, event: wl.Output.Event, output: *Output) void
output.scale = @intCast(ev.factor);
},
.name => |ev| {
if (output.name) |old_name| utils.gpa.free(old_name);
output.name = utils.gpa.dupe(u8, mem.span(ev.name)) catch @panic("Out of memory");
},
else => {},

View file

@ -52,7 +52,15 @@ pub fn destroy(wm: *WindowManager) void {
seat.destroy();
}
}
{
var it = wm.orphan_windows.safeIterator(.forward);
while (it.next()) |window| {
window.link.remove();
window.destroy();
}
}
wm.river_window_manager_v1.destroy();
utils.gpa.destroy(wm);
}

View file

@ -489,6 +489,7 @@ pub fn destroy(xkb_bindings: *XkbBindings) void {
binding.xkb_binding_v1.destroy();
utils.gpa.destroy(binding);
}
xkb_bindings.xkb_bindings_v1.destroy();
utils.gpa.destroy(xkb_bindings);
}

View file

@ -40,12 +40,11 @@ pub fn main() !void {
_ = fcft.init(.auto, false, fcft_log_level);
defer fcft.fini();
const wayland_display_var = try utils.gpa.dupeZ(u8, process.getEnvVarOwned(utils.gpa, "WAYLAND_DISPLAY") catch {
fatal("Error getting WAYLAND_DISPLAY environment variable. Exiting", .{});
});
defer utils.gpa.free(wayland_display_var);
const wayland_display_var = posix.getenvZ("WAYLAND_DISPLAY") orelse {
fatal("WAYLAND_DISPLAY environment variable not set. Exiting", .{});
};
const wl_display = wl.Display.connect(null) catch {
const wl_display = wl.Display.connect(wayland_display_var) catch {
fatal("Error connecting to Wayland server. Exiting", .{});
};
defer wl_display.disconnect();