Author: Armin Rigo <ar...@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)) -@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit