[pygobject] Use qdata for wrapper retrieval in toggle reference notifications
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Use qdata for wrapper retrieval in toggle reference notifications
- Date: Fri, 11 Oct 2013 06:12:09 +0000 (UTC)
commit 27e9f6ede021fc58e952491b67d69c2a5cdd6acb
Author: Simon Feltman <sfeltman src gnome org>
Date: Tue Oct 1 17:09:39 2013 -0700
Use qdata for wrapper retrieval in toggle reference notifications
Replace usage of user data holding PyGObject wrappers in toggle ref
notifications with GObject qdata retrieval. This fixes thread safety issues
where a toggle notify may be called from another thread during the PyGObject
wrappers dealloc. In this case the toggle notify is blocked because the GIL
is held in dealloc, and when it continues, the user data would be holding an
invalid PyGObject wrapper. Using qdata solves this by ensuring the wrapper
retrieval is done within the safety of the GIL and may turn up as NULL.
https://bugzilla.gnome.org/show_bug.cgi?id=709223
gi/_gobject/pygobject.c | 21 ++++++++++++++-------
1 files changed, 14 insertions(+), 7 deletions(-)
---
diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c
index 126c80e..65d5de9 100644
--- a/gi/_gobject/pygobject.c
+++ b/gi/_gobject/pygobject.c
@@ -592,15 +592,22 @@ pygobject_register_class(PyObject *dict, const gchar *type_name,
static void
pyg_toggle_notify (gpointer data, GObject *object, gboolean is_last_ref)
{
- PyGObject *self = (PyGObject*) data;
+ PyGObject *self;
PyGILState_STATE state;
state = pyglib_gil_state_ensure();
- if (is_last_ref)
- Py_DECREF(self);
- else
- Py_INCREF(self);
+ /* Avoid thread safety problems by using qdata for wrapper retrieval
+ * instead of the user data argument.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=709223
+ */
+ self = (PyGObject *)g_object_get_qdata (object, pygobject_wrapper_key);
+ if (self) {
+ if (is_last_ref)
+ Py_DECREF(self);
+ else
+ Py_INCREF(self);
+ }
pyglib_gil_state_release(state);
}
@@ -621,7 +628,7 @@ pygobject_switch_to_toggle_ref(PyGObject *self)
/* Note that add_toggle_ref will never immediately call back into
pyg_toggle_notify */
Py_INCREF((PyObject *) self);
- g_object_add_toggle_ref(self->obj, pyg_toggle_notify, self);
+ g_object_add_toggle_ref(self->obj, pyg_toggle_notify, NULL);
g_object_unref(self->obj);
}
@@ -1178,7 +1185,7 @@ pygobject_clear(PyGObject *self)
if (self->obj) {
g_object_set_qdata_full(self->obj, pygobject_wrapper_key, NULL, NULL);
if (self->inst_dict) {
- g_object_remove_toggle_ref(self->obj, pyg_toggle_notify, self);
+ g_object_remove_toggle_ref(self->obj, pyg_toggle_notify, NULL);
self->private_flags.flags &= ~PYGOBJECT_USING_TOGGLE_REF;
} else {
Py_BEGIN_ALLOW_THREADS;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]