[pygobject] make sure caller allocated structs are freed when they go out of scope
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] make sure caller allocated structs are freed when they go out of scope
- Date: Fri, 30 Jul 2010 09:07:01 +0000 (UTC)
commit c9da5782e6c633d9af43ee85075e9ee65db09780
Author: John (J5) Palmieri <johnp redhat com>
Date: Fri Jul 9 13:14:42 2010 -0400
make sure caller allocated structs are freed when they go out of scope
* Move struct transfer checks from pygi-arguments to pygi-invoke
* add better warning if an unknown struct is fully transfered
* only free GValues we create in the invoke cleanup. All other structs
get cleaned up when they go out of scope in python
* Fixes issues with caller allocated treeiters getting freed to early
* this is a fix to crashes in the current test suite when API's returning
TreeIters were annotated as out caller-allocates so no new tests
are needed
https://bugzilla.gnome.org/show_bug.cgi?id=623969
gi/pygi-argument.c | 13 +++++--------
gi/pygi-invoke.c | 46 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 45 insertions(+), 14 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 24f996e..6bea63f 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -1368,15 +1368,12 @@ _pygi_argument_to_object (GArgument *arg,
break;
}
- if (transfer != GI_TRANSFER_NOTHING)
- g_warning ("Transfer mode should be set to None for "
- "struct types as there is no way to free "
- "them safely. Ignoring transfer mode "
- "to prevent a potential invalid free. "
- "This may cause a leak in your application.");
-
+ /* Only structs created in invoke can be safely marked
+ * GI_TRANSFER_EVERYTHING. Trust that invoke has
+ * filtered correctly
+ */
object = _pygi_struct_new ( (PyTypeObject *) py_type, arg->v_pointer,
- FALSE);
+ transfer == GI_TRANSFER_EVERYTHING);
Py_DECREF (py_type);
} else {
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 022874e..2bd1978 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -675,11 +675,14 @@ _process_invocation_state (struct invocation_state *state,
state->return_type_info, state->return_arg.v_pointer);
} else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
if (transfer != GI_TRANSFER_NOTHING)
- g_warning ("Transfer mode should be set to None for "
+ g_warning ("Return argument in %s returns a struct "
+ "with a transfer mode of \"full\" "
+ "Transfer mode should be set to None for "
"struct types as there is no way to free "
"them safely. Ignoring transfer mode "
"to prevent a potential invalid free. "
- "This may cause a leak in your application.");
+ "This may cause a leak in your application.",
+ g_base_info_get_name ( (GIBaseInfo *) function_info) );
state->return_value = _pygi_struct_new (py_type, state->return_arg.v_pointer, FALSE);
} else {
@@ -795,6 +798,36 @@ _process_invocation_state (struct invocation_state *state,
/* Convert the argument. */
PyObject *obj;
+ /* If we created it, deallocate when it goes out of scope
+ * otherwise it is unsafe to deallocate random structures
+ * we are given
+ */
+ if (type_tag == GI_TYPE_TAG_INTERFACE) {
+ GIBaseInfo *info;
+ GIInfoType info_type;
+
+ info = g_type_info_get_interface (state->arg_type_infos[i]);
+ g_assert (info != NULL);
+ info_type = g_base_info_get_type (info);
+
+ if ( (info_type == GI_INFO_TYPE_STRUCT) &&
+ !g_struct_info_is_foreign((GIStructInfo *) info) ) {
+ if (g_arg_info_is_caller_allocates (state->arg_infos[i])) {
+ transfer = GI_TRANSFER_EVERYTHING;
+ } else if (transfer == GI_TRANSFER_EVERYTHING) {
+ transfer = GI_TRANSFER_NOTHING;
+ g_warning ("Out argument %u in %s returns a struct "
+ "with a transfer mode of \"full\". "
+ "Transfer mode should be set to \"none\" for "
+ "struct type returns as there is no way to free "
+ "them safely. Ignoring transfer mode "
+ "to prevent a potential invalid free. "
+ "This may cause a leak in your application.",
+ i, g_base_info_get_name ( (GIBaseInfo *) function_info) );
+ }
+ }
+ }
+
obj = _pygi_argument_to_object (state->args[i], state->arg_type_infos[i], transfer);
if (obj == NULL) {
/* TODO: release arguments. */
@@ -923,15 +956,16 @@ _free_invocation_state (struct invocation_state *state)
/* caller-allocates applies only to structs right now
* the GI scanner is overzealous when marking parameters
- * as caller-allocates, so we only free if this was a struct
+ * as caller-allocates
*/
if (info_type == GI_INFO_TYPE_STRUCT) {
- /* special case GValues so we make sure to unset them */
+ /* special case GValues since all other structs are returned
+ * as is and freed when they go out of scope
+ */
if (g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info) == G_TYPE_VALUE) {
g_value_unset ( (GValue *) state->args[i]);
+ g_free (state->args[i]);
}
-
- g_free (state->args[i]);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]