Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8d109cb

Browse files
committed
Antoine Pitrou's patch for bug 2507; exception state lives too long in
3.0.
1 parent 96de30a commit 8d109cb

2 files changed

Lines changed: 42 additions & 2 deletions

File tree

Lib/test/test_exceptions.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import unittest
66
import pickle
7+
import weakref
78

89
from test.test_support import TESTFN, unlink, run_unittest
910

@@ -400,8 +401,9 @@ def testUnicodeStrUsage(self):
400401
self.failUnless(str(Exception('a')))
401402
self.failUnless(str(Exception('a')))
402403

403-
def testExceptionCleanup(self):
404-
# Make sure "except V as N" exceptions are cleaned up properly
404+
def testExceptionCleanupNames(self):
405+
# Make sure the local variable bound to the exception instance by
406+
# an "except" statement is only visible inside the except block.
405407

406408
try:
407409
raise Exception()
@@ -410,6 +412,31 @@ def testExceptionCleanup(self):
410412
del e
411413
self.failIf('e' in locals())
412414

415+
def testExceptionCleanupState(self):
416+
# Make sure exception state is cleaned up as soon as the except
417+
# block is left. See #2507
418+
419+
class MyException(Exception):
420+
def __init__(self, obj):
421+
self.obj = obj
422+
class MyObj:
423+
pass
424+
425+
def inner_raising_func():
426+
# Create some references in exception value and traceback
427+
local_ref = obj
428+
raise MyException(obj)
429+
430+
obj = MyObj()
431+
wr = weakref.ref(obj)
432+
try:
433+
inner_raising_func()
434+
except MyException as e:
435+
pass
436+
obj = None
437+
obj = wr()
438+
self.failUnless(obj is None, "%s" % obj)
439+
413440

414441
def test_main():
415442
run_unittest(ExceptionTests)

Python/ceval.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,19 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
14771477
"'finally' pops bad exception");
14781478
why = WHY_EXCEPTION;
14791479
}
1480+
/*
1481+
Make sure the exception state is cleaned up before
1482+
the end of an except block. This ensures objects
1483+
referenced by the exception state are not kept
1484+
alive too long.
1485+
See #2507.
1486+
*/
1487+
if (tstate->frame->f_exc_type != NULL)
1488+
reset_exc_info(tstate);
1489+
else {
1490+
assert(tstate->frame->f_exc_value == NULL);
1491+
assert(tstate->frame->f_exc_traceback == NULL);
1492+
}
14801493
Py_DECREF(v);
14811494
break;
14821495

0 commit comments

Comments
 (0)