Reference cycles with Python and Gtk4

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.connect('destroy', lambda *_: print('destroy'))
        self.set_child(Gtk.Button(label='Test', action_name='win.test'))
        test_action = Gio.SimpleAction.new('test', None)
        test_action.connect('activate', self.on_test)
        self.add_action(test_action)

    def on_test(self, *args):
        print('test')

The destroy signal is never emitted because the SimpleAction holds a reference to self. It worked with Gtk3, it destroys the window even though there are still references from Python.

How is this supposed to work?

The reference cycle has always been there, and there was always a reference leak underneath PyGObject, unfortunately.

The “destroy” signal is emitted because something else was calling GObject.run_dispose(), which runs regardless of the amount of references held. GTK4 does not forcibly run the dispose cycle, so the “destroy” signal is not going to be emitted until the last reference is dropped.

You could decide to call self.run_dispose() yourself when the window is closed; it is basically a way to force a garbage collection pass. At that point, inside the “destroy” handler you could remove all the signal connections you added yourself.

I now use the window-removed signal to disconnect all signals and bindings. The destroy signal is emitted and I was able to use weak_ref to verify that all objects are properly disposed. Thank you.

Not necessary.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.