diff --git a/src/apprt/gtk/class/application.zig b/src/apprt/gtk/class/application.zig index 14232f1f0..7ab7c9c20 100644 --- a/src/apprt/gtk/class/application.zig +++ b/src/apprt/gtk/class/application.zig @@ -1548,7 +1548,7 @@ pub const Application = extern struct { diag.close(); diag.unref(); // strong ref from get() } - priv.config_errors_dialog.set(null); + priv.config_errors_dialog.deinit(); if (priv.signal_source) |v| { if (glib.Source.remove(v) == 0) { log.warn("unable to remove signal source", .{}); diff --git a/src/apprt/gtk/class/command_palette.zig b/src/apprt/gtk/class/command_palette.zig index 3ec7dfa0d..aaec00587 100644 --- a/src/apprt/gtk/class/command_palette.zig +++ b/src/apprt/gtk/class/command_palette.zig @@ -609,7 +609,7 @@ const Command = extern struct { switch (priv.data) { .regular => {}, .jump => |*j| { - j.surface.set(null); + j.surface.deinit(); }, } diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 473ae3daf..24e6e70b6 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -647,7 +647,7 @@ pub const SplitTree = extern struct { fn dispose(self: *Self) callconv(.c) void { const priv = self.private(); - priv.last_focused.set(null); + priv.last_focused.deinit(); if (priv.rebuild_source) |v| { if (glib.Source.remove(v) == 0) { log.warn("unable to remove rebuild source", .{}); diff --git a/src/apprt/gtk/class/window.zig b/src/apprt/gtk/class/window.zig index f9e3b9841..caa7ddb4a 100644 --- a/src/apprt/gtk/class/window.zig +++ b/src/apprt/gtk/class/window.zig @@ -1296,7 +1296,7 @@ pub const Window = extern struct { priv.handle_active_state_source = null; } - priv.command_palette.set(null); + priv.command_palette.deinit(); if (priv.config) |v| { v.unref(); diff --git a/src/apprt/gtk/weak_ref.zig b/src/apprt/gtk/weak_ref.zig index f689e45fa..73cc6e511 100644 --- a/src/apprt/gtk/weak_ref.zig +++ b/src/apprt/gtk/weak_ref.zig @@ -22,6 +22,23 @@ pub fn WeakRef(comptime T: type) type { } } + /// Release this weak reference. + /// + /// You MUST call this before the memory holding this struct is freed, + /// which in practice means from the owner's `dispose`. The target keeps + /// a pointer to this `GWeakRef` so that it can clear it when the target + /// is finalized; if this memory is gone by then, the target walks into + /// whatever now occupies it. That is an invalid read at best, and can + /// hang: the target takes a lock inside each registered weak ref, and + /// reused memory with the low bit set is a lock nothing will release. + /// + /// `set(null)` also unregisters and remains valid. This exists so the + /// requirement has a name at the use site rather than looking like an + /// ordinary assignment. + pub fn deinit(self: *Self) void { + self.ref.clear(); + } + /// Get a strong reference to the object, or null if the object /// has been finalized. This increases the reference count by one. pub fn get(self: *Self) ?*T {