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

commit8f50a8281c5c728e38b9efa9e4580432cbdc780f
parente843829233
authorIsaac Freund <[email protected]>
date2024-04-08 15:18
View: add more assertions around destruction

This should make leaks like the one fixed by the previous commit harder
to write.

 river/Root.zig         | 2 +-
 river/View.zig         | 8 +++++++-
 river/XdgToplevel.zig  | 4 ++--
 river/XwaylandView.zig | 4 ++--
 4 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/river/Root.zig b/river/Root.zig
index a33bf63..258129d 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -726,7 +726,7 @@ fn commitTransaction(root: *Root) void {
         var it = root.hidden.inflight.focus_stack.safeIterator(.forward);
         while (it.next()) |view| {
             view.dropSavedSurfaceTree();
-            if (view.destroying) view.destroy();
+            if (view.destroying) view.destroy(.assert);
         }
     }
 
diff --git a/river/View.zig b/river/View.zig
index 84a0214..b0542ad 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -228,8 +228,9 @@ pub fn create(impl: Impl) error{OutOfMemory}!*View {
 /// If saved buffers of the view are currently in use by a transaction,
 /// mark this view for destruction when the transaction completes. Otherwise
 /// destroy immediately.
-pub fn destroy(view: *View) void {
+pub fn destroy(view: *View, when: enum { lazy, assert }) void {
     assert(view.impl == .none);
+    assert(!view.mapped);
 
     view.destroying = true;
 
@@ -249,6 +250,11 @@ pub fn destroy(view: *View) void {
         if (view.output_before_evac) |name| util.gpa.free(name);
 
         util.gpa.destroy(view);
+    } else {
+        switch (when) {
+            .lazy => {},
+            .assert => unreachable,
+        }
     }
 }
 
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index b307f26..58e18c7 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -81,7 +81,7 @@ pub fn create(wlr_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
         .view = undefined,
         .wlr_toplevel = wlr_toplevel,
     } });
-    errdefer view.destroy();
+    errdefer view.destroy(.assert);
 
     const toplevel = &view.impl.toplevel;
 
@@ -219,7 +219,7 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
 
     const view = toplevel.view;
     view.impl = .none;
-    view.destroy();
+    view.destroy(.lazy);
 }
 
 fn handleMap(listener: *wl.Listener(void)) void {
diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig
index 9aa5b63..7155868 100644
--- a/river/XwaylandView.zig
+++ b/river/XwaylandView.zig
@@ -64,7 +64,7 @@ pub fn create(xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!void {
         .view = undefined,
         .xwayland_surface = xwayland_surface,
     } });
-    errdefer view.destroy();
+    errdefer view.destroy(.assert);
 
     const xwayland_view = &view.impl.xwayland_view;
     xwayland_view.view = view;
@@ -142,7 +142,7 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
 
     const view = xwayland_view.view;
     view.impl = .none;
-    view.destroy();
+    view.destroy(.lazy);
 }
 
 fn handleAssociate(listener: *wl.Listener(void)) void {