@@ -1141,6 +1141,23 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
11411141 f->f_exc_traceback = tmp; \
11421142 }
11431143
1144+ #define RESTORE_AND_CLEAR_EXC_STATE () \
1145+ { \
1146+ PyObject *type, *value, *tb; \
1147+ type = tstate->exc_type; \
1148+ value = tstate->exc_value; \
1149+ tb = tstate->exc_traceback; \
1150+ tstate->exc_type = f->f_exc_type; \
1151+ tstate->exc_value = f->f_exc_value; \
1152+ tstate->exc_traceback = f->f_exc_traceback; \
1153+ f->f_exc_type = NULL; \
1154+ f->f_exc_value = NULL; \
1155+ f->f_exc_traceback = NULL; \
1156+ Py_XDECREF(type); \
1157+ Py_XDECREF(value); \
1158+ Py_XDECREF(tb); \
1159+ }
1160+
11441161/* Start of code */
11451162
11461163 if (f == NULL )
@@ -3001,10 +3018,25 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
30013018 retval = NULL ;
30023019
30033020fast_yield :
3004- if (co -> co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN ))
3005- /* Put aside the current exception state and restore that of the
3006- calling frame. */
3007- SWAP_EXC_STATE ();
3021+ if (co -> co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN )) {
3022+ /* The purpose of this block is to put aside the generator's exception
3023+ state and restore that of the calling frame. If the current
3024+ exception state is from the caller, we clear the exception values
3025+ on the generator frame, so they are not swapped back in latter. The
3026+ origin of the current exception state is determined by checking for
3027+ except handler blocks, which we must be in iff a new exception
3028+ state came into existence in this frame. (An uncaught exception
3029+ would have why == WHY_EXCEPTION, and we wouldn't be here). */
3030+ int i ;
3031+ for (i = 0 ; i < f -> f_iblock ; i ++ )
3032+ if (f -> f_blockstack [i ].b_type == EXCEPT_HANDLER )
3033+ break ;
3034+ if (i == f -> f_iblock )
3035+ /* We did not create this exception. */
3036+ RESTORE_AND_CLEAR_EXC_STATE ()
3037+ else
3038+ SWAP_EXC_STATE ()
3039+ }
30083040
30093041 if (tstate -> use_tracing ) {
30103042 if (tstate -> c_tracefunc ) {
0 commit comments