1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>, Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "pygi-marshal-cleanup.h"
23 _cleanup_caller_allocates (PyGIInvokeState *state,
27 gboolean was_processed)
29 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)cache;
31 /* check GValue first because GValue is also a boxed sub-type */
32 if (g_type_is_a (iface_cache->g_type, G_TYPE_VALUE)) {
35 g_slice_free (GValue, data);
36 } else if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
39 return; /* will be cleaned up at deallocation */
40 size = g_struct_info_get_size (iface_cache->interface_info);
41 g_slice_free1 (size, data);
42 } else if (iface_cache->is_foreign) {
44 return; /* will be cleaned up at deallocation */
45 pygi_struct_foreign_release ((GIBaseInfo *)iface_cache->interface_info,
49 return; /* will be cleaned up at deallocation */
55 * Cleanup during invoke can happen in multiple
56 * stages, each of which can be the result of a
57 * successful compleation of that stage or an error
58 * occured which requires partial cleanup.
60 * For the most part, either the C interface being
61 * invoked or the python object which wraps the
62 * parameters, handle their lifecycles but in some
63 * cases, where we have intermediate objects,
64 * or when we fail processing a parameter, we need
65 * to handle the clean up manually.
67 * There are two argument processing stages.
68 * They are the in stage, where we process python
69 * parameters into their C counterparts, and the out
70 * stage, where we process out C parameters back
71 * into python objects. The in stage also sets up
72 * temporary out structures for caller allocated
73 * parameters which need to be cleaned up either on
74 * in stage failure or at the completion of the out
75 * stage (either success or failure)
77 * The in stage must call one of these cleanup functions:
78 * - pygi_marshal_cleanup_args_from_py_marshal_success
79 * (continue to out stage)
80 * - pygi_marshal_cleanup_args_from_py_parameter_fail
81 * (final, exit from invoke)
83 * The out stage must call one of these cleanup functions which are all final:
84 * - pygi_marshal_cleanup_args_to_py_marshal_success
85 * - pygi_marshal_cleanup_args_return_fail
86 * - pygi_marshal_cleanup_args_to_py_parameter_fail
90 pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState *state,
91 PyGICallableCache *cache)
95 for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
96 PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
97 PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
98 gpointer cleanup_data = state->args_cleanup_data[i];
100 /* Only cleanup using args_cleanup_data when available.
101 * It is the responsibility of the various "from_py" marshalers to return
102 * cleanup_data which is then passed into their respective cleanup function.
103 * PyGIInvokeState.args_cleanup_data stores this data (via _invoke_marshal_in_args)
104 * for the duration of the invoke up until this point.
106 if (cleanup_func && cleanup_data != NULL && arg_cache->py_arg_index >= 0 &&
107 arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
108 PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index);
109 cleanup_func (state, arg_cache, py_arg, cleanup_data, TRUE);
110 state->args_cleanup_data[i] = NULL;
116 pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState *state,
117 PyGICallableCache *cache)
120 /* clean up the return if available */
121 if (cache->return_cache != NULL) {
122 PyGIMarshalCleanupFunc cleanup_func = cache->return_cache->to_py_cleanup;
123 if (cleanup_func && state->return_arg.v_pointer != NULL)
127 state->return_arg.v_pointer,
131 /* Now clean up args */
132 cache_item = cache->to_py_args;
134 PyGIArgCache *arg_cache = (PyGIArgCache *) cache_item->data;
135 PyGIMarshalCleanupFunc cleanup_func = arg_cache->to_py_cleanup;
136 gpointer data = state->arg_values[arg_cache->c_arg_index].v_pointer;
138 if (cleanup_func != NULL && data != NULL)
144 else if (arg_cache->is_caller_allocates && data != NULL) {
145 _cleanup_caller_allocates (state,
152 cache_item = cache_item->next;
157 pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState *state,
158 PyGICallableCache *cache,
159 gssize failed_arg_index)
163 state->failed = TRUE;
165 for (i = 0; i < _pygi_callable_cache_args_len (cache) && i <= failed_arg_index; i++) {
166 PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
167 PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
168 gpointer cleanup_data = state->args_cleanup_data[i];
169 PyObject *py_arg = NULL;
171 if (arg_cache->py_arg_index < 0) {
174 py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index);
176 if (cleanup_func && cleanup_data != NULL &&
177 arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON) {
182 i < failed_arg_index);
184 } else if (arg_cache->is_caller_allocates && cleanup_data != NULL) {
185 _cleanup_caller_allocates (state,
191 state->args_cleanup_data[i] = NULL;
196 pygi_marshal_cleanup_args_return_fail (PyGIInvokeState *state,
197 PyGICallableCache *cache)
199 state->failed = TRUE;
203 pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state,
204 PyGICallableCache *cache,
205 gssize failed_to_py_arg_index)
207 state->failed = TRUE;