[Python-checkins] cpython (merge 3.2 -> default): merge 3.2 (#12475)

benjamin.peterson python-checkins at python.org
Sun Jul 3 20:44:36 CEST 2011


http://hg.python.org/cpython/rev/33dca840938d
changeset:   71154:33dca840938d
parent:      71153:65e57bead934
parent:      71152:36bc49565281
user:        Benjamin Peterson <benjamin at python.org>
date:        Sun Jul 03 13:48:36 2011 -0500
summary:
  merge 3.2 (#12475)

files:
  Lib/test/test_exceptions.py |  15 +++++++++++++++
  Misc/NEWS                   |   3 +++
  Python/ceval.c              |   9 +++++----
  3 files changed, 23 insertions(+), 4 deletions(-)


diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -567,6 +567,21 @@
             del g
             self.assertEqual(sys.exc_info()[0], TypeError)
 
+    def test_generator_leaking2(self):
+        # See issue 12475.
+        def g():
+            yield
+        try:
+            raise RuntimeError
+        except RuntimeError:
+            it = g()
+            next(it)
+        try:
+            next(it)
+        except StopIteration:
+            pass
+        self.assertEqual(sys.exc_info(), (None, None, None))
+
     def test_generator_finalizing_and_exc_info(self):
         # See #7173
         def simple_gen():
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #12475: Prevent generators from leaking their exception state into the
+  callers frame as they return for the last time.
+
 - Issue #12291: You can now load multiple marshalled objects from a stream,
   with other data interleaved between marshalled objects.
 
diff --git a/Python/ceval.c b/Python/ceval.c
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1865,10 +1865,6 @@
             retval = POP();
             f->f_stacktop = stack_pointer;
             why = WHY_YIELD;
-            /* Put aside the current exception state and restore
-               that of the calling frame. This only serves when
-               "yield" is used inside an except handler. */
-            SWAP_EXC_STATE();
             goto fast_yield;
 
         TARGET(POP_EXCEPT)
@@ -3005,6 +3001,11 @@
         retval = NULL;
 
 fast_yield:
+    if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN))
+        /* Put aside the current exception state and restore that of the
+           calling frame. */
+        SWAP_EXC_STATE();
+
     if (tstate->use_tracing) {
         if (tstate->c_tracefunc) {
             if (why == WHY_RETURN || why == WHY_YIELD) {

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list