File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -566,6 +566,21 @@ def yield_raise():
566566 del g
567567 self .assertEqual (sys .exc_info ()[0 ], TypeError )
568568
569+ def test_generator_leaking2 (self ):
570+ # See issue 12475.
571+ def g ():
572+ yield
573+ try :
574+ raise RuntimeError
575+ except RuntimeError :
576+ it = g ()
577+ next (it )
578+ try :
579+ next (it )
580+ except StopIteration :
581+ pass
582+ self .assertEqual (sys .exc_info (), (None , None , None ))
583+
569584 def test_generator_finalizing_and_exc_info (self ):
570585 # See #7173
571586 def simple_gen ():
Original file line number Diff line number Diff line change @@ -10,6 +10,9 @@ What's New in Python 3.2.2?
1010Core and Builtins
1111-----------------
1212
13+ - Issue #12475: Prevent generators from leaking their exception state into the
14+ callers frame as they return for the last time.
15+
1316Library
1417-------
1518
Original file line number Diff line number Diff line change @@ -1881,10 +1881,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
18811881 retval = POP ();
18821882 f -> f_stacktop = stack_pointer ;
18831883 why = WHY_YIELD ;
1884- /* Put aside the current exception state and restore
1885- that of the calling frame. This only serves when
1886- "yield" is used inside an except handler. */
1887- SWAP_EXC_STATE ();
18881884 goto fast_yield ;
18891885
18901886 TARGET (POP_EXCEPT )
@@ -3021,6 +3017,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
30213017 retval = NULL ;
30223018
30233019fast_yield :
3020+ if (co -> co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN ))
3021+ /* Put aside the current exception state and restore that of the
3022+ calling frame. */
3023+ SWAP_EXC_STATE ();
3024+
30243025 if (tstate -> use_tracing ) {
30253026 if (tstate -> c_tracefunc ) {
30263027 if (why == WHY_RETURN || why == WHY_YIELD ) {
You can’t perform that action at this time.
0 commit comments