diff options
author | Benjamin Berg <benjamin@sipsolutions.net> | 2022-12-27 00:34:21 +0100 |
---|---|---|
committer | Benjamin Berg <benjamin@sipsolutions.net> | 2022-12-27 11:22:26 +0100 |
commit | c8d89fdf69b70f0add71e07413e2b3b23687ab6b (patch) | |
tree | f9494da83031c983044dfc54f93feebe0c824ef2 /gi/overrides/GLib.py | |
parent | c57bd80c07a4f846c4ebcc55dcd10f629319c0be (diff) | |
download | pygobject-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.py | 10 |
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 |