[pygobject] Clear return value of closures to zero when an exception occures



commit 3b3251593ea107f06b160234b0ca5393cb39ac1b
Author: Simon Feltman <sfeltman src gnome org>
Date:   Tue Jul 2 23:02:17 2013 -0700

    Clear return value of closures to zero when an exception occures
    
    For return types other than void, set the ffi closure return argument
    to 0 when a Python exception occures. This a good default in general
    but also has the side affect of fixing failing idle callbacks
    by causing them to be removed from main loops (after their stack
    is printed).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=702552

 gi/pygi-closure.c |   14 ++++++++++++++
 tests/test_gi.py  |    8 ++++++++
 2 files changed, 22 insertions(+), 0 deletions(-)
---
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index f30fa52..99e15a1 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -108,6 +108,19 @@ _pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
 }
 
 static void
+_pygi_closure_clear_retval (GICallableInfo *callable_info, gpointer retval)
+{
+    GITypeInfo return_type_info;
+    GITypeTag return_type_tag;
+
+    g_callable_info_load_return_type (callable_info, &return_type_info);
+    return_type_tag = g_type_info_get_tag (&return_type_info);
+    if (return_type_tag != GI_TYPE_TAG_VOID) {
+        *((ffi_arg *) retval) = 0;
+    }
+}
+
+static void
 _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
                                             GITypeInfo *type_info,
                                             GITransfer transfer)
@@ -546,6 +559,7 @@ _pygi_closure_handle (ffi_cif *cif,
     Py_DECREF (py_args);
 
     if (retval == NULL) {
+        _pygi_closure_clear_retval (closure->info, result);
         PyErr_Print();
         goto end;
     }
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 1c983eb..8dd0126 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -2069,6 +2069,10 @@ class TestPythonGObject(unittest.TestCase):
             self.variants = variants
             self.n_variants = n_variants
 
+    class ErrorObject(GIMarshallingTests.Object):
+        def do_vfunc_return_value_only(self):
+            raise ValueError('Return value should be 0')
+
     def test_object(self):
         self.assertTrue(issubclass(self.Object, GIMarshallingTests.Object))
 
@@ -2228,6 +2232,10 @@ class TestPythonGObject(unittest.TestCase):
         _object.call_vfunc_with_callback()
         self.assertTrue(_object.worked)
 
+    def test_exception_in_vfunc_return_value(self):
+        obj = self.ErrorObject()
+        self.assertEqual(obj.vfunc_return_value_only(), 0)
+
 
 class TestMultiOutputArgs(unittest.TestCase):
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]