summaryrefslogtreecommitdiff
path: root/gi/overrides/GLib.py
diff options
context:
space:
mode:
authorBenjamin Berg <benjamin@sipsolutions.net>2022-12-27 00:34:21 +0100
committerBenjamin Berg <benjamin@sipsolutions.net>2022-12-27 11:22:26 +0100
commitc8d89fdf69b70f0add71e07413e2b3b23687ab6b (patch)
treef9494da83031c983044dfc54f93feebe0c824ef2 /gi/overrides/GLib.py
parentc57bd80c07a4f846c4ebcc55dcd10f629319c0be (diff)
downloadpygobject-c8d89fdf69b70f0add71e07413e2b3b23687ab6b.tar.gz
source: Fix source finalization in some corner casesbenzea/gsource-fix2
GLib will call the finalize handler when the GSource is destroyed. We already enforce destruction from __del__, however, the final reference might only be dropped later on because the main context (or something else) is holding another reference. The main case where this happens is if the source is pending at the time, e.g. if it is being destroyed while it is dispatching. After destroy is called on the source, the only callback that can still be called is finalize. As such, we can simply call finalize immediately and rely on GLib cleaning up the underlying GSource at a later point. Note that it can also happen that __del__ is not called at all if the interpreter quits. In this case, neither __del__ nor finalize will be called even though the underlying GSource may be finalized correctly. Compared to the previous behaviour this is a big improvement, as it would crash previously.
Diffstat (limited to 'gi/overrides/GLib.py')
-rw-r--r--gi/overrides/GLib.py10
1 files changed, 7 insertions, 3 deletions
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index 78d309b6..0425d50f 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -525,12 +525,16 @@ class Source(GLib.Source):
def __del__(self):
if hasattr(self, '__pygi_custom_source'):
+ # We destroy and finalize the box from here, as GLib might hold
+ # a reference (e.g. while the source is pending), delaying the
+ # finalize call until a later point.
self.destroy()
- # XXX: We have to unref the underlying source while the Python
- # wrapper is still valid, so the source can call into the
- # wrapper methods for the finalized callback.
+ self.finalize()
self._clear_boxed()
+ def finalize(self):
+ pass
+
def set_callback(self, fn, user_data=None):
if hasattr(self, '__pygi_custom_source'):
# use our custom pygi_source_set_callback() if for a GSource object