[gjs: 1/3] object: Do not call any function on disposed GObject pointers
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/3] object: Do not call any function on disposed GObject pointers
- Date: Sat, 13 Mar 2021 18:05:13 +0000 (UTC)
commit d37d6604ca0d50b9be408acd637e8073e30500c7
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Fri Mar 12 21:25:24 2021 +0100
object: Do not call any function on disposed GObject pointers
After an object is disposed we should really not perform anything with
it, however we may end up calling some GObject functions during
disposition.
In particular, we try to print its name, unset the qdata and unref it
again.
So during disassociation always ensure that the object we're
disassociating has not been already destroyed, before doing such
operations.
gi/object.cpp | 15 +++++++++------
gi/toggle.cpp | 16 +++++++---------
gi/toggle.h | 2 +-
installed-tests/js/testGtk3.js | 7 ++-----
4 files changed, 19 insertions(+), 21 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index c811a065..68410514 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1297,7 +1297,9 @@ void
ObjectInstance::release_native_object(void)
{
discard_wrapper();
- if (m_uses_toggle_ref)
+ if (m_gobj_disposed)
+ m_ptr.release();
+ else if (m_uses_toggle_ref)
g_object_remove_toggle_ref(m_ptr.release(), wrapped_gobj_toggle_notify,
nullptr);
else
@@ -1479,9 +1481,6 @@ ObjectInstance::disassociate_js_gobject(void)
{
bool had_toggle_down, had_toggle_up;
- if (!m_gobj_disposed)
- g_object_weak_unref(m_ptr.get(), wrapped_gobj_dispose_notify, this);
-
auto& toggle_queue = ToggleQueue::get_default();
std::tie(had_toggle_down, had_toggle_up) = toggle_queue.cancel(m_ptr.get());
if (had_toggle_down != had_toggle_up) {
@@ -1491,8 +1490,12 @@ ObjectInstance::disassociate_js_gobject(void)
m_ptr.get(), type_name());
}
- /* Fist, remove the wrapper pointer from the wrapped GObject */
- unset_object_qdata();
+ if (!m_gobj_disposed) {
+ g_object_weak_unref(m_ptr.get(), wrapped_gobj_dispose_notify, this);
+
+ /* Fist, remove the wrapper pointer from the wrapped GObject */
+ unset_object_qdata();
+ }
/* Now release all the resources the current wrapper has */
invalidate_closure_list(&m_closures);
diff --git a/gi/toggle.cpp b/gi/toggle.cpp
index 5f3d4386..4f7db32f 100644
--- a/gi/toggle.cpp
+++ b/gi/toggle.cpp
@@ -71,19 +71,17 @@ ToggleQueue::is_queued(GObject *gobj) const
return {has_toggle_down, has_toggle_up};
}
-std::pair<bool, bool>
-ToggleQueue::cancel(GObject *gobj)
-{
+std::pair<bool, bool> ToggleQueue::cancel(GObject* gobj) {
debug("cancel", gobj);
std::lock_guard<std::mutex> hold(lock);
bool had_toggle_down = find_and_erase_operation_locked(gobj, DOWN);
bool had_toggle_up = find_and_erase_operation_locked(gobj, UP);
- gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "ToggleQueue: %p (%s) was %s", gobj,
- G_OBJECT_TYPE_NAME(gobj),
- had_toggle_down && had_toggle_up ? "queued to toggle BOTH"
- : had_toggle_down ? "queued to toggle DOWN"
- : had_toggle_up ? "queued to toggle UP"
- : "not queued");
+ gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "ToggleQueue: %p was %s", gobj,
+ had_toggle_down && had_toggle_up
+ ? "queued to toggle BOTH"
+ : had_toggle_down ? "queued to toggle DOWN"
+ : had_toggle_up ? "queued to toggle UP"
+ : "not queued");
return {had_toggle_down, had_toggle_up};
}
diff --git a/gi/toggle.h b/gi/toggle.h
index f7f8eac8..e77c5419 100644
--- a/gi/toggle.h
+++ b/gi/toggle.h
@@ -66,7 +66,7 @@ private:
* are / were queued. is_queued() just checks and does not modify. */
[[nodiscard]] std::pair<bool, bool> is_queued(GObject* gobj) const;
/* Cancels pending toggles and returns whether any were queued. */
- std::pair<bool, bool> cancel(GObject *gobj);
+ std::pair<bool, bool> cancel(GObject* gobj);
/* Pops a toggle from the queue and processes it. Call this if you don't
* want to wait for it to be processed in idle time. Returns false if queue
diff --git a/installed-tests/js/testGtk3.js b/installed-tests/js/testGtk3.js
index f3f6e724..15187b67 100644
--- a/installed-tests/js/testGtk3.js
+++ b/installed-tests/js/testGtk3.js
@@ -180,14 +180,11 @@ describe('Gtk overrides', function () {
GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_CRITICAL,
'*destroy*');
- let BadLabel = GObject.registerClass(class BadLabel extends Gtk.Label {
+ const BadLabel = GObject.registerClass(class BadLabel extends Gtk.Label {
vfunc_destroy() {}
});
- let w = new Gtk.Window();
- w.add(new BadLabel());
-
- w.destroy();
+ new BadLabel();
System.gc();
GLib.test_assert_expected_messages_internal('Gjs', 'testGtk3.js', 0,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]