From d01444d325c0e62b846b795e3443e97932271e17 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 7 Mar 2010 17:14:15 +0000 Subject: Merged revisions 78766 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r78766 | benjamin.peterson | 2010-03-07 11:10:51 -0600 (Sun, 07 Mar 2010) | 1 line prevent generator finalization from invalidating sys.exc_info() #7173 ........ --- Lib/test/test_exceptions.py | 17 ++++++++++++++++- Misc/NEWS | 2 ++ Python/ceval.c | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 6aa8102..b10835d 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -6,7 +6,8 @@ import unittest import pickle import weakref -from test.support import TESTFN, unlink, run_unittest, captured_output +from test.support import (TESTFN, unlink, run_unittest, captured_output, + gc_collect) # XXX This is not really enough, each *operation* should be tested! @@ -554,6 +555,20 @@ class ExceptionTests(unittest.TestCase): del g self.assertEquals(sys.exc_info()[0], TypeError) + def test_generator_finalizing_and_exc_info(self): + # See #7173 + def simple_gen(): + yield 1 + def run_gen(): + gen = simple_gen() + try: + raise RuntimeError + except RuntimeError: + return next(gen) + run_gen() + gc_collect() + self.assertEqual(sys.exc_info(), (None, None, None)) + def test_3114(self): # Bug #3114: in its destructor, MyObject retrieves a pointer to # obsolete and/or deallocated objects. diff --git a/Misc/NEWS b/Misc/NEWS index 30234ed..71db3ca 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ What's New in Python 3.1.2? Core and Builtins ----------------- +- Issue #7173: Generator finalization could invalidate sys.exc_info(). + Library ------- diff --git a/Python/ceval.c b/Python/ceval.c index 8a24f11..f793db3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1107,7 +1107,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) assert(stack_pointer != NULL); f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ - if (f->f_code->co_flags & CO_GENERATOR) { + if (co->co_flags & CO_GENERATOR && !throwflag) { if (f->f_exc_type != NULL && f->f_exc_type != Py_None) { /* We were in an except handler when we left, restore the exception state which was put aside -- cgit v0.12