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"
21 #include "pygi-foreign.h"
25 _cleanup_caller_allocates (PyGIInvokeState
*state
,
29 gboolean was_processed
)
31 PyGIInterfaceCache
*iface_cache
= (PyGIInterfaceCache
*)cache
;
33 /* check GValue first because GValue is also a boxed sub-type */
34 if (g_type_is_a (iface_cache
->g_type
, G_TYPE_VALUE
)) {
37 g_slice_free (GValue
, data
);
38 } else if (g_type_is_a (iface_cache
->g_type
, G_TYPE_BOXED
)) {
41 return; /* will be cleaned up at deallocation */
42 size
= g_struct_info_get_size (iface_cache
->interface_info
);
43 g_slice_free1 (size
, data
);
44 } else if (iface_cache
->is_foreign
) {
46 return; /* will be cleaned up at deallocation */
47 pygi_struct_foreign_release ((GIBaseInfo
*)iface_cache
->interface_info
,
51 return; /* will be cleaned up at deallocation */
57 * Cleanup during invoke can happen in multiple
58 * stages, each of which can be the result of a
59 * successful compleation of that stage or an error
60 * occured which requires partial cleanup.
62 * For the most part, either the C interface being
63 * invoked or the python object which wraps the
64 * parameters, handle their lifecycles but in some
65 * cases, where we have intermediate objects,
66 * or when we fail processing a parameter, we need
67 * to handle the clean up manually.
69 * There are two argument processing stages.
70 * They are the in stage, where we process python
71 * parameters into their C counterparts, and the out
72 * stage, where we process out C parameters back
73 * into python objects. The in stage also sets up
74 * temporary out structures for caller allocated
75 * parameters which need to be cleaned up either on
76 * in stage failure or at the completion of the out
77 * stage (either success or failure)
79 * The in stage must call one of these cleanup functions:
80 * - pygi_marshal_cleanup_args_from_py_marshal_success
81 * (continue to out stage)
82 * - pygi_marshal_cleanup_args_from_py_parameter_fail
83 * (final, exit from invoke)
85 * The out stage must call one of these cleanup functions which are all final:
86 * - pygi_marshal_cleanup_args_to_py_marshal_success
87 * - pygi_marshal_cleanup_args_return_fail
88 * - pygi_marshal_cleanup_args_to_py_parameter_fail
92 pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState
*state
,
93 PyGICallableCache
*cache
)
96 PyObject
*error_type
, *error_value
, *error_traceback
;
97 gboolean have_error
= !!PyErr_Occurred ();
100 PyErr_Fetch (&error_type
, &error_value
, &error_traceback
);
102 for (i
= 0; i
< _pygi_callable_cache_args_len (cache
); i
++) {
103 PyGIArgCache
*arg_cache
= _pygi_callable_cache_get_arg (cache
, i
);
104 PyGIMarshalCleanupFunc cleanup_func
= arg_cache
->from_py_cleanup
;
105 gpointer cleanup_data
= state
->args
[i
].arg_cleanup_data
;
107 /* Only cleanup using args_cleanup_data when available.
108 * It is the responsibility of the various "from_py" marshalers to return
109 * cleanup_data which is then passed into their respective cleanup function.
110 * PyGIInvokeState.args_cleanup_data stores this data (via _invoke_marshal_in_args)
111 * for the duration of the invoke up until this point.
113 if (cleanup_func
&& cleanup_data
!= NULL
&& arg_cache
->py_arg_index
>= 0 &&
114 arg_cache
->direction
& PYGI_DIRECTION_FROM_PYTHON
) {
115 PyObject
*py_arg
= PyTuple_GET_ITEM (state
->py_in_args
, arg_cache
->py_arg_index
);
116 cleanup_func (state
, arg_cache
, py_arg
, cleanup_data
, TRUE
);
117 state
->args
[i
].arg_cleanup_data
= NULL
;
122 PyErr_Restore (error_type
, error_value
, error_traceback
);
126 pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState
*state
,
127 PyGICallableCache
*cache
)
131 PyObject
*error_type
, *error_value
, *error_traceback
;
132 gboolean have_error
= !!PyErr_Occurred ();
135 PyErr_Fetch (&error_type
, &error_value
, &error_traceback
);
137 /* clean up the return if available */
138 if (cache
->return_cache
!= NULL
) {
139 PyGIMarshalToPyCleanupFunc cleanup_func
= cache
->return_cache
->to_py_cleanup
;
140 if (cleanup_func
&& state
->return_arg
.v_pointer
!= NULL
)
143 state
->to_py_return_arg_cleanup_data
,
144 state
->return_arg
.v_pointer
,
148 /* Now clean up args */
149 cache_item
= cache
->to_py_args
;
151 PyGIArgCache
*arg_cache
= (PyGIArgCache
*) cache_item
->data
;
152 PyGIMarshalToPyCleanupFunc cleanup_func
= arg_cache
->to_py_cleanup
;
153 gpointer data
= state
->args
[arg_cache
->c_arg_index
].arg_value
.v_pointer
;
155 if (cleanup_func
!= NULL
&& data
!= NULL
)
158 state
->args
[arg_cache
->c_arg_index
].to_py_arg_cleanup_data
,
161 else if (arg_cache
->is_caller_allocates
&& data
!= NULL
) {
162 _cleanup_caller_allocates (state
,
164 state
->args
[arg_cache
->c_arg_index
].to_py_arg_cleanup_data
,
170 cache_item
= cache_item
->next
;
174 PyErr_Restore (error_type
, error_value
, error_traceback
);
178 pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState
*state
,
179 PyGICallableCache
*cache
,
180 gssize failed_arg_index
)
183 PyObject
*error_type
, *error_value
, *error_traceback
;
184 gboolean have_error
= !!PyErr_Occurred ();
187 PyErr_Fetch (&error_type
, &error_value
, &error_traceback
);
189 state
->failed
= TRUE
;
191 for (i
= 0; i
< _pygi_callable_cache_args_len (cache
) && i
<= (guint
)failed_arg_index
; i
++) {
192 PyGIArgCache
*arg_cache
= _pygi_callable_cache_get_arg (cache
, i
);
193 PyGIMarshalCleanupFunc cleanup_func
= arg_cache
->from_py_cleanup
;
194 gpointer cleanup_data
= state
->args
[i
].arg_cleanup_data
;
195 PyObject
*py_arg
= NULL
;
197 if (arg_cache
->py_arg_index
< 0) {
200 py_arg
= PyTuple_GET_ITEM (state
->py_in_args
, arg_cache
->py_arg_index
);
202 if (cleanup_func
&& cleanup_data
!= NULL
&&
203 arg_cache
->direction
== PYGI_DIRECTION_FROM_PYTHON
) {
208 i
< (guint
)failed_arg_index
);
210 } else if (arg_cache
->is_caller_allocates
&& cleanup_data
!= NULL
) {
211 _cleanup_caller_allocates (state
,
217 state
->args
[i
].arg_cleanup_data
= NULL
;
221 PyErr_Restore (error_type
, error_value
, error_traceback
);
225 pygi_marshal_cleanup_args_return_fail (PyGIInvokeState
*state
,
226 PyGICallableCache
*cache
)
228 state
->failed
= TRUE
;
232 pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState
*state
,
233 PyGICallableCache
*cache
,
234 gssize failed_to_py_arg_index
)
236 state
->failed
= TRUE
;