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

Reply via email to