[pypy-commit] pypy py3.5: A leak, caused by having a single prebuilt instance of GeneratorExit.
arigo
pypy.commits at gmail.com
Thu Jun 28 04:53:56 EDT 2018
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r94784:0017e9688738
Date: 2018-06-28 10:53 +0200
http://bitbucket.org/pypy/pypy/changeset/0017e9688738/
Log: A leak, caused by having a single prebuilt instance of
GeneratorExit. This is a really bad idea in Python 3.x, because
traceback entries will keep being added to that instance, and leak
massively. Argh!
This checkin contains code to explode at translation-time if another
prebuilt instance of W_BaseException is ever seen.
Thanks hubo!
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -270,7 +270,7 @@
if self.frame is None:
return # nothing to do in this case
space = self.space
- operr = get_generator_exit(space)
+ operr = None
# note: w_yielded_from is always None if 'self.running'
w_yf = self.w_yielded_from
if w_yf is not None:
@@ -278,6 +278,8 @@
self._gen_close_iter(space)
except OperationError as e:
operr = e
+ if operr is None:
+ operr = OperationError(space.w_GeneratorExit, space.w_None)
try:
self.send_error(operr)
except OperationError as e:
@@ -451,11 +453,6 @@
space.call_function(space.w_StopIteration, w_value))
- at specialize.memo()
-def get_generator_exit(space):
- return OperationError(space.w_GeneratorExit,
- space.call_function(space.w_GeneratorExit))
-
def gen_close_iter(space, w_yf):
# This helper function is used by close() and throw() to
# close a subiterator being delegated to by yield-from.
diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py
--- a/pypy/module/exceptions/interp_exceptions.py
+++ b/pypy/module/exceptions/interp_exceptions.py
@@ -235,6 +235,13 @@
self.descr_settraceback(space, w_traceback)
return self
+ def _cleanup_(self):
+ raise Exception("Prebuilt instances of (subclasses of) BaseException "
+ "must be avoided in Python 3.x. They have mutable "
+ "attributes related to tracebacks, so whenever they "
+ "are raised in the actual program they will "
+ "accumulate more frames and never free them.")
+
def _new(cls, basecls=None):
if basecls is None:
basecls = cls
More information about the pypy-commit
mailing list