git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit376b84d80d055b29217cb04ae2e92941e4109a0e
parentb197faa412
authorIsaac Freund <[email protected]>
date2020-06-02 13:45
Clean up some memory leaks

 include/bindings.c   |  4 ++++
 include/bindings.h   |  1 +
 river/Config.zig     |  6 +++++-
 river/Control.zig    |  3 ++-
 river/Decoration.zig | 13 +++++++++++++
 river/Root.zig       | 14 ++++++++++----
 river/Server.zig     | 11 +++++++----
 7 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/include/bindings.c b/include/bindings.c
index 0eaf76d..7b16c09 100644
--- a/include/bindings.c
+++ b/include/bindings.c
@@ -35,3 +35,7 @@ struct wlr_output *river_wlr_noop_add_output(struct wlr_backend *backend) {
 bool river_wlr_output_is_noop(struct wlr_output *output) {
     return wlr_output_is_noop(output);
 }
+
+void river_wlr_backend_destory(struct wlr_backend *backend) {
+    wlr_backend_destroy(backend);
+}
diff --git a/include/bindings.h b/include/bindings.h
index d8b9358..9643836 100644
--- a/include/bindings.h
+++ b/include/bindings.h
@@ -31,5 +31,6 @@ struct wlr_session *river_wlr_backend_get_session(struct wlr_backend *backend);
 struct wlr_backend *river_wlr_noop_backend_create(struct wl_display *display);
 struct wlr_output *river_wlr_noop_add_output(struct wlr_backend *backend);
 bool river_wlr_output_is_noop(struct wlr_output *output);
+void river_wlr_backend_destory(struct wlr_backend *backend);
 
 #endif // RIVER_BINDINGS_H
diff --git a/river/Config.zig b/river/Config.zig
index 541e82b..5f39fb3 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -62,6 +62,10 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void {
 
 pub fn deinit(self: Self, allocator: *std.mem.Allocator) void {
     self.mode_to_id.deinit();
-    for (self.modes.items) |*mode| mode.deinit();
+    for (self.modes.items) |mode| {
+        for (mode.items) |mapping| mapping.deinit(allocator);
+        mode.deinit();
+    }
     self.modes.deinit();
+    self.float_filter.deinit();
 }
diff --git a/river/Control.zig b/river/Control.zig
index e9ae576..1c12b42 100644
--- a/river/Control.zig
+++ b/river/Control.zig
@@ -85,12 +85,13 @@ fn runCommand(
     const seat = self.server.input_manager.default_seat;
 
     var args = std.ArrayList([]const u8).init(allocator);
+    defer args.deinit();
 
     var i: usize = 0;
     const data = @ptrCast([*]const u8, wl_array.?.data);
     while (i < wl_array.?.size) {
         const slice = std.mem.spanZ(@ptrCast([*:0]const u8, &data[i]));
-        args.append(std.mem.dupe(allocator, u8, slice) catch unreachable) catch unreachable;
+        args.append(slice) catch unreachable;
 
         i += slice.len + 1;
     }
diff --git a/river/Decoration.zig b/river/Decoration.zig
index 91c5bed..b96450c 100644
--- a/river/Decoration.zig
+++ b/river/Decoration.zig
@@ -27,6 +27,7 @@ const DecorationManager = @import("DecorationManager.zig");
 decoration_manager: *DecorationManager,
 wlr_xdg_toplevel_decoration: *c.wlr_xdg_toplevel_decoration_v1,
 
+listen_destroy: c.wl_listener,
 listen_request_mode: c.wl_listener,
 
 pub fn init(
@@ -37,12 +38,24 @@ pub fn init(
     self.decoration_manager = decoration_manager;
     self.wlr_xdg_toplevel_decoration = wlr_xdg_toplevel_decoration;
 
+    self.listen_destroy.notify = handleDestroy;
+    c.wl_signal_add(&self.wlr_xdg_toplevel_decoration.events.destroy, &self.listen_destroy);
+
     self.listen_request_mode.notify = handleRequestMode;
     c.wl_signal_add(&self.wlr_xdg_toplevel_decoration.events.request_mode, &self.listen_request_mode);
 
     handleRequestMode(&self.listen_request_mode, self.wlr_xdg_toplevel_decoration);
 }
 
+fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
+    const self = @fieldParentPtr(Self, "listen_destroy", listener.?);
+    const allocator = self.decoration_manager.server.allocator;
+    const node = @fieldParentPtr(std.SinglyLinkedList(Self).Node, "data", self);
+
+    self.decoration_manager.decorations.remove(node);
+    allocator.destroy(node);
+}
+
 fn handleRequestMode(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
     const self = @fieldParentPtr(Self, "listen_request_mode", listener.?);
     // TODO: we might need to take this configure serial and do a transaction
diff --git a/river/Root.zig b/river/Root.zig
index 562aa3c..fe07e7e 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -79,11 +79,17 @@ pub fn init(self: *Self, server: *Server) !void {
 }
 
 pub fn deinit(self: *Self) void {
-    while (self.outputs.pop()) |output_node| {
-        output_node.data.deinit();
-        self.server.allocator.destroy(output_node);
-    }
+    // Need to remove these listeners as the noop output will be destroyed with
+    // the noop backend triggering the destroy event. However,
+    // Output.handleDestroy is not intended to handle the noop output being
+    // destroyed.
+    c.wl_list_remove(&self.noop_output.listen_destroy.link);
+    c.wl_list_remove(&self.noop_output.listen_frame.link);
+    c.wl_list_remove(&self.noop_output.listen_mode.link);
+
     c.wlr_output_layout_destroy(self.wlr_output_layout);
+
+    if (c.wl_event_source_remove(self.transaction_timer) < 0) unreachable;
 }
 
 pub fn addOutput(self: *Self, wlr_output: *c.wlr_output) void {
diff --git a/river/Server.zig b/river/Server.zig
index e46a619..f700746 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -136,13 +136,16 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void {
 /// Free allocated memory and clean up
 pub fn deinit(self: *Self) void {
     // Note: order is important here
-    if (build_options.xwayland) {
-        c.wlr_xwayland_destroy(self.wlr_xwayland);
-    }
+    if (build_options.xwayland) c.wlr_xwayland_destroy(self.wlr_xwayland);
+
     c.wl_display_destroy_clients(self.wl_display);
+
+    self.root.deinit();
+
     c.wl_display_destroy(self.wl_display);
+    c.river_wlr_backend_destory(self.noop_backend);
+
     self.input_manager.deinit();
-    self.root.deinit();
     self.config.deinit(self.allocator);
 }