diff -r a9305102c892 Python/ceval.c --- a/Python/ceval.c Fri Jan 30 20:11:10 2015 +0100 +++ b/Python/ceval.c Sat Jan 31 01:57:37 2015 +0100 @@ -648,6 +648,7 @@ enum why_code { WHY_YIELD = 0x0040 /* 'yield' operator */ }; +static void swap_exc_state(PyThreadState *, PyFrameObject *); static enum why_code do_raise(PyObject *, PyObject *, PyObject *); static int unpack_iterable(PyObject *, int, PyObject **); @@ -940,6 +941,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int assert(stack_pointer != NULL); f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ + if (co->co_flags & CO_GENERATOR) + swap_exc_state(tstate, f); + #ifdef LLTRACE lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; #endif @@ -3016,6 +3020,9 @@ fast_yield: /* pop frame */ exit_eval_frame: + if (co->co_flags & CO_GENERATOR) + swap_exc_state(tstate, f); + Py_LeaveRecursiveCall(); tstate->frame = f->f_back; @@ -3468,6 +3475,21 @@ reset_exc_info(PyThreadState *tstate) Py_XDECREF(tmp_tb); } +static void +swap_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *tmp; + tmp = tstate->exc_type; + tstate->exc_type = f->f_exc_type; + f->f_exc_type = tmp; + tmp = tstate->exc_value; + tstate->exc_value = f->f_exc_value; + f->f_exc_value = tmp; + tmp = tstate->exc_traceback; + tstate->exc_traceback = f->f_exc_traceback; + f->f_exc_traceback = tmp; +} + /* Logic for the raise statement (too complicated for inlining). This *consumes* a reference count to each of its arguments. */ static enum why_code