[nautilus/wip/coreyberla/window-dispose: 6/7] window: Don't finalize twice
- From: António Fernandes <antoniof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/coreyberla/window-dispose: 6/7] window: Don't finalize twice
- Date: Thu, 1 Sep 2022 20:27:34 +0000 (UTC)
commit f50fc9d098c4b5c1d373b66908f5a0d9b99504d7
Author: António Fernandes <antoniof gnome org>
Date: Thu Sep 1 19:34:13 2022 +0100
window: Don't finalize twice
The pad controller owns a reference to the window (as an action group)
and the window (as a widget) owns a reference to the pad controller.
This is a reference cycle.
Usually, reference cycles are resolved in dispose(), which can get
called multiple times. However, GTK removes the controllers during
finalize(). We end up calling finalize() recursively, which is a big
problem.
So our only option is to manually remove the controller before starting
the destruction of the window.
src/nautilus-window.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
---
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 51a7db0de..9ab46a10a 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -126,6 +126,10 @@ struct _NautilusWindow
gulong bookmarks_id;
GQueue *tab_data_queue;
+
+ /* Pad controller which holds a reference to the window. Kept around to
+ * break reference-counting cycles during finalization. */
+ GtkPadController *pad_controller;
};
enum
@@ -1663,6 +1667,13 @@ nautilus_window_close (NautilusWindow *window)
nautilus_window_save_geometry (window);
nautilus_window_set_active_slot (window, NULL);
+ /* The pad controller hold a reference to the window, creating a cycle.
+ * Usually, reference cycles are resolved in dispose(), but GTK removes the
+ * controllers in finalize(), so our only option is to manually remove it
+ * here before starting the destruction of the window. */
+ gtk_widget_remove_controller (GTK_WIDGET (window),
+ GTK_EVENT_CONTROLLER (window->pad_controller));
+
gtk_window_destroy (GTK_WINDOW (window));
}
@@ -2051,7 +2062,6 @@ static void
nautilus_window_init (NautilusWindow *window)
{
GtkWindowGroup *window_group;
- GtkPadController *pad_controller;
GtkEventController *controller;
g_type_ensure (NAUTILUS_TYPE_TOOLBAR);
@@ -2084,11 +2094,15 @@ nautilus_window_init (NautilusWindow *window)
window->tab_data_queue = g_queue_new ();
- pad_controller = gtk_pad_controller_new (G_ACTION_GROUP (window), NULL);
- gtk_pad_controller_set_action_entries (pad_controller,
+ /* Attention: this creates a reference cycle: the pad controller owns a
+ * reference to the window (as an action group) and the window (as a widget)
+ * owns a reference to the pad controller. To break this, we must remove
+ * the controller from the window before destroying the window. */
+ window->pad_controller = gtk_pad_controller_new (G_ACTION_GROUP (window), NULL);
+ gtk_pad_controller_set_action_entries (window->pad_controller,
pad_actions, G_N_ELEMENTS (pad_actions));
gtk_widget_add_controller (GTK_WIDGET (window),
- GTK_EVENT_CONTROLLER (pad_controller));
+ GTK_EVENT_CONTROLLER (window->pad_controller));
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
gtk_widget_add_controller (GTK_WIDGET (window), controller);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]