Swap exception context inside generators
authorVitja Makarov <vitja.makarov@gmail.com>
Wed, 20 Apr 2011 12:47:55 +0000 (16:47 +0400)
committerVitja Makarov <vitja.makarov@gmail.com>
Wed, 20 Apr 2011 12:47:55 +0000 (16:47 +0400)
Cython/Compiler/ExprNodes.py
Cython/Compiler/ParseTreeTransforms.py

index db4e69932debf764f7266d37c896c9db757f54ab..54d19884653d665251cea2d927b8c6e1f72e9f28 100755 (executable)
@@ -8511,6 +8511,17 @@ static PyObject *__Pyx_Generator_Throw(PyObject *gen, PyObject *args, CYTHON_UNU
 typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *);
 """,
 impl="""
+static CYTHON_INLINE void __Pyx_Generator_ExceptionClear(struct __pyx_Generator_object *self)
+{
+    Py_XDECREF(self->exc_type);
+    Py_XDECREF(self->exc_value);
+    Py_XDECREF(self->exc_traceback);
+
+    self->exc_type = NULL;
+    self->exc_value = NULL;
+    self->exc_traceback = NULL;
+}
+
 static CYTHON_INLINE PyObject *__Pyx_Generator_SendEx(struct __pyx_Generator_object *self, PyObject *value)
 {
     PyObject *retval;
@@ -8535,10 +8546,21 @@ static CYTHON_INLINE PyObject *__Pyx_Generator_SendEx(struct __pyx_Generator_obj
         return NULL;
     }
 
+
+    if (value)
+        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
+    else
+        __Pyx_Generator_ExceptionClear(self);
+
     self->is_running = 1;
     retval = self->body((PyObject *) self, value);
     self->is_running = 0;
 
+    if (retval)
+        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
+    else
+        __Pyx_Generator_ExceptionClear(self);
+
     return retval;
 }
 
@@ -8596,5 +8618,5 @@ static PyObject *__Pyx_Generator_Throw(PyObject *self, PyObject *args, CYTHON_UN
 }
 """,
 proto_block='utility_code_proto_before_types',
-requires=[Nodes.raise_utility_code],
+requires=[Nodes.raise_utility_code, Nodes.swap_exception_utility_code],
 )
index ca683e07d97fc2d4806b877aec96db28cf7e7658..9ee649d119ed118249d3c0ef5e91dc049474d119 100644 (file)
@@ -1557,6 +1557,12 @@ class CreateClosureClasses(CythonTransform):
                           is_cdef=True)
         klass.declare_var(pos=pos, name='resume_label', cname='resume_label', type=PyrexTypes.c_int_type,
                           is_cdef=True)
+        klass.declare_var(pos=pos, name='exc_type', cname='exc_type',
+                          type=PyrexTypes.py_object_type, is_cdef=True)
+        klass.declare_var(pos=pos, name='exc_value', cname='exc_value',
+                          type=PyrexTypes.py_object_type, is_cdef=True)
+        klass.declare_var(pos=pos, name='exc_traceback', cname='exc_traceback',
+                          type=PyrexTypes.py_object_type, is_cdef=True)
 
         import TypeSlots
         e = klass.declare_pyfunction('send', pos)