[gjs/gnome-40: 15/30] object: Safely handle disposal when happening from other thread
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/gnome-40: 15/30] object: Safely handle disposal when happening from other thread
- Date: Wed, 5 May 2021 20:41:26 +0000 (UTC)
commit 760012f80ce30a7a96e044fa5f6f981587a52cdd
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Mon Mar 29 04:16:26 2021 +0200
object: Safely handle disposal when happening from other thread
In case we dispose an object from another thread we still queue a toggle
down event to happen in an idle, so that it can be picked by main
thread at next iteration.
However, in such case we'll have no more the instance set on the object
private data. We still keep track of it through the disposed data
though, so we can use it to trigger a toggle down event.
It's an error if we get an invalid ("true") pointer here, so we log
about it.
(cherry-picked from commit c4fc8213)
gi/object.cpp | 19 +++++++++++++++++--
installed-tests/js/testGObjectDestructionAccess.js | 16 ++++++++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index e18620ec..072c46c2 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1257,12 +1257,27 @@ static void
toggle_handler(GObject *gobj,
ToggleQueue::Direction direction)
{
+ auto* self = ObjectInstance::for_gobject(gobj);
+
+ if (G_UNLIKELY(!self)) {
+ void* disposed = g_object_get_qdata(gobj, ObjectBase::disposed_quark());
+
+ if (G_UNLIKELY(disposed == gjs_int_to_pointer(DISPOSED_OBJECT))) {
+ g_critical("Handling toggle %s for an unknown object %p",
+ direction == ToggleQueue::UP ? "up" : "down", gobj);
+ return;
+ }
+
+ // In this case the object has been disposed but its wrapper not yet
+ self = static_cast<ObjectInstance*>(disposed);
+ }
+
switch (direction) {
case ToggleQueue::UP:
- ObjectInstance::for_gobject(gobj)->toggle_up();
+ self->toggle_up();
break;
case ToggleQueue::DOWN:
- ObjectInstance::for_gobject(gobj)->toggle_down();
+ self->toggle_down();
break;
default:
g_assert_not_reached();
diff --git a/installed-tests/js/testGObjectDestructionAccess.js
b/installed-tests/js/testGObjectDestructionAccess.js
index 6504d844..b5523804 100644
--- a/installed-tests/js/testGObjectDestructionAccess.js
+++ b/installed-tests/js/testGObjectDestructionAccess.js
@@ -290,4 +290,20 @@ describe('Disposed or finalized GObject', function () {
GjsTestTools.unref_other_thread(file);
file.run_dispose();
});
+
+ it('can be disposed from other thread', function () {
+ let file = Gio.File.new_for_path('/');
+ file.expandMeWithToggleRef = true;
+ file.ref();
+ GjsTestTools.unref_other_thread(file);
+ GjsTestTools.run_dispose_other_thread(file);
+ });
+
+ it('can be garbage collected once disposed from other thread', function () {
+ let file = Gio.File.new_for_path('/');
+ file.expandMeWithToggleRef = true;
+ GjsTestTools.run_dispose_other_thread(file);
+ file = null;
+ System.gc();
+ });
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]