summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2021-05-14 01:56:41 +0100
committerColin Watson <cjwatson@debian.org>2021-05-14 01:56:41 +0100
commit7db889e77fc2c51e6e2977366041bea0c8ae1eaa (patch)
tree70604c9c0fc18be0be89dbb6928a05bae7b49207
parent5450d23ab2598e3553e9d4020b4488101c3ecc3e (diff)
downloadzope-tal-7db889e77fc2c51e6e2977366041bea0c8ae1eaa.tar.gz
Avoid traceback reference cycle in TALInterpreter.do_onError_tal
In Python 3, exceptions have a ``__traceback__`` attribute containing their associated traceback. Storing an exception in a local variable of a frame present in that traceback thus creates a reference cycle. Avoid this by explicitly deleting the exception value when we're finished with it.
-rw-r--r--CHANGES.rst2
-rw-r--r--src/zope/tal/talinterpreter.py13
2 files changed, 10 insertions, 5 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index db87896..89411df 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -5,7 +5,7 @@
4.5 (unreleased)
================
-- Nothing changed yet.
+- Avoid traceback reference cycle in ``TALInterpreter.do_onError_tal``.
4.4 (2018-10-05)
diff --git a/src/zope/tal/talinterpreter.py b/src/zope/tal/talinterpreter.py
index 82154db..ce2837e 100644
--- a/src/zope/tal/talinterpreter.py
+++ b/src/zope/tal/talinterpreter.py
@@ -987,10 +987,15 @@ class TALInterpreter(object):
# handled.
except:
exc = sys.exc_info()[1]
- self.restoreState(state)
- engine = self.engine
- engine.beginScope()
- error = engine.createErrorInfo(exc, self.position)
+ try:
+ self.restoreState(state)
+ engine = self.engine
+ engine.beginScope()
+ error = engine.createErrorInfo(exc, self.position)
+ finally:
+ # Avoid traceback reference cycle due to the __traceback__
+ # attribute on Python 3.
+ del exc
engine.setLocal('error', error)
try:
self.interpret(handler)