[Python-3000-checkins] r62847 - in python/branches/py3k: Lib/test/test_exceptions.py Python/ceval.c

barry.warsaw python-3000-checkins at python.org
Thu May 8 06:26:36 CEST 2008


Author: barry.warsaw
Date: Thu May  8 06:26:35 2008
New Revision: 62847

Log:
Antoine Pitrou's patch for bug 2507; exception state lives too long in
3.0.


Modified:
   python/branches/py3k/Lib/test/test_exceptions.py
   python/branches/py3k/Python/ceval.c

Modified: python/branches/py3k/Lib/test/test_exceptions.py
==============================================================================
--- python/branches/py3k/Lib/test/test_exceptions.py	(original)
+++ python/branches/py3k/Lib/test/test_exceptions.py	Thu May  8 06:26:35 2008
@@ -4,6 +4,7 @@
 import sys
 import unittest
 import pickle
+import weakref
 
 from test.test_support import TESTFN, unlink, run_unittest
 
@@ -400,8 +401,9 @@
         self.failUnless(str(Exception('a')))
         self.failUnless(str(Exception('a')))
 
-    def testExceptionCleanup(self):
-        # Make sure "except V as N" exceptions are cleaned up properly
+    def testExceptionCleanupNames(self):
+        # Make sure the local variable bound to the exception instance by
+        # an "except" statement is only visible inside the except block.
 
         try:
             raise Exception()
@@ -410,6 +412,31 @@
             del e
         self.failIf('e' in locals())
 
+    def testExceptionCleanupState(self):
+        # Make sure exception state is cleaned up as soon as the except
+        # block is left. See #2507
+
+        class MyException(Exception):
+            def __init__(self, obj):
+                self.obj = obj
+        class MyObj:
+            pass
+
+        def inner_raising_func():
+            # Create some references in exception value and traceback
+            local_ref = obj
+            raise MyException(obj)
+
+        obj = MyObj()
+        wr = weakref.ref(obj)
+        try:
+            inner_raising_func()
+        except MyException as e:
+            pass
+        obj = None
+        obj = wr()
+        self.failUnless(obj is None, "%s" % obj)
+
 
 def test_main():
     run_unittest(ExceptionTests)

Modified: python/branches/py3k/Python/ceval.c
==============================================================================
--- python/branches/py3k/Python/ceval.c	(original)
+++ python/branches/py3k/Python/ceval.c	Thu May  8 06:26:35 2008
@@ -1477,6 +1477,19 @@
 					"'finally' pops bad exception");
 				why = WHY_EXCEPTION;
 			}
+			/*
+			  Make sure the exception state is cleaned up before
+			  the end of an except block. This ensures objects
+			  referenced by the exception state are not kept
+			  alive too long.
+			  See #2507.
+			*/
+			if (tstate->frame->f_exc_type != NULL)
+				reset_exc_info(tstate);
+			else {
+				assert(tstate->frame->f_exc_value == NULL);
+				assert(tstate->frame->f_exc_traceback == NULL);
+			}
 			Py_DECREF(v);
 			break;
 


More information about the Python-3000-checkins mailing list