[pygobject] Fix to Python marshaling leaks for arrays holding GVariants
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Fix to Python marshaling leaks for arrays holding GVariants
- Date: Tue, 8 Oct 2013 01:19:55 +0000 (UTC)
commit 31263ac117027446c8e2fd1b56d7e348384aabef
Author: Simon Feltman <sfeltman src gnome org>
Date: Sun Oct 6 21:54:15 2013 -0700
Fix to Python marshaling leaks for arrays holding GVariants
Add early check for array items holding pointers and simply assign the
pointer to GIArgument.v_pointer prior giving it to the per-item marshaler.
This simplifies marshaling and fixes leaks regarding arrays of GVariants by
removing the unneeded g_variant_ref_sink (variants are always pointers).
Conditionalize the use of g_variant_ref_sink based on transfer mode in the
per-item marshaler. This fixes a reference leak where we are given ownership
of the variant (transfer full) but added a new ref anyway.
https://bugzilla.gnome.org/show_bug.cgi?id=693402
gi/pygi-marshal-to-py.c | 34 ++++++++++++++++++----------------
1 files changed, 18 insertions(+), 16 deletions(-)
---
diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c
index 2dc7f71..2c7a8de 100644
--- a/gi/pygi-marshal-to-py.c
+++ b/gi/pygi-marshal-to-py.c
@@ -351,36 +351,35 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
item_size = g_array_get_element_size (array_);
for (i = 0; i < array_->len; i++) {
- GIArgument item_arg;
+ GIArgument item_arg = {0};
PyObject *py_item;
+ /* If we are receiving an array of pointers, simply assign the pointer
+ * and move on, letting the per-item marshaler deal with the
+ * various transfer modes and ref counts (e.g. g_variant_ref_sink).
+ */
if (seq_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
+
+ } else if (item_arg_cache->is_pointer) {
+ item_arg.v_pointer = g_array_index (array_, gpointer, i);
+
} else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
- gboolean is_gvariant = iface_cache->g_type == G_TYPE_VARIANT;
// FIXME: This probably doesn't work with boxed types or gvalues. See fx.
_pygi_marshal_from_py_array()
switch (g_base_info_get_type (iface_cache->interface_info)) {
case GI_INFO_TYPE_STRUCT:
- if (is_gvariant) {
- g_assert (item_size == sizeof (gpointer));
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- item_arg.v_pointer = g_variant_ref_sink (g_array_index (array_, gpointer,
i));
- else
- item_arg.v_pointer = g_array_index (array_, gpointer, i);
- } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
!item_arg_cache->is_pointer &&
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
!g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
/* array elements are structs */
gpointer *_struct = g_malloc (item_size);
memcpy (_struct, array_->data + i * item_size,
item_size);
item_arg.v_pointer = _struct;
- } else if (item_arg_cache->is_pointer)
- /* array elements are pointers to values */
- item_arg.v_pointer = g_array_index (array_, gpointer, i);
- else
+ } else {
item_arg.v_pointer = array_->data + i * item_size;
+ }
break;
default:
item_arg.v_pointer = g_array_index (array_, gpointer, i);
@@ -858,10 +857,13 @@ _pygi_marshal_to_py_interface_struct (GIArgument *arg,
transfer == GI_TRANSFER_EVERYTHING);
}
} else if (g_type_is_a (g_type, G_TYPE_VARIANT)) {
- /* Note we do not use transfer for the structs free_on_dealloc because
- * GLib.Variant overrides __del__ to call "g_variant_unref". */
+ /* Note: sink the variant (add a ref) only if we are not transfered ownership.
+ * GLib.Variant overrides __del__ which will then call "g_variant_unref" for
+ * cleanup in either case. */
if (py_type) {
- g_variant_ref_sink (arg->v_pointer);
+ if (transfer == GI_TRANSFER_NOTHING) {
+ g_variant_ref_sink (arg->v_pointer);
+ }
py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
arg->v_pointer,
FALSE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]