diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2017-08-20 23:33:06 +0200 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2017-08-20 23:33:06 +0200 |
commit | e0c94ef2d98b2c5193d152fa2603de782dcb9d58 (patch) | |
tree | cdc1bffc45d0a1248bdcbbe4408aa86b8ba5ba0b | |
parent | 69f3183a3357086a4c443c77c7e49ba99d29fd3c (diff) | |
download | cython-e0c94ef2d98b2c5193d152fa2603de782dcb9d58.tar.gz |
Keep direct closure of generators and coroutines intact during cleanup by disabling their tp_clear() as they still need their closure for handling the final GeneratorExit call.
-rw-r--r-- | Cython/Compiler/ParseTreeTransforms.py | 3 | ||||
-rw-r--r-- | tests/run/generator_frame_cycle.py | 7 |
2 files changed, 10 insertions, 0 deletions
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index aee77f81d..4edaf0923 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -2660,6 +2660,9 @@ class CreateClosureClasses(CythonTransform): class_scope = entry.type.scope class_scope.is_internal = True class_scope.is_closure_class_scope = True + if node.is_async_def or node.is_generator: + # Generators need their closure intact during cleanup as they resume to handle GeneratorExit + class_scope.directives['no_gc_clear'] = True if Options.closure_freelist_size: class_scope.directives['freelist'] = Options.closure_freelist_size diff --git a/tests/run/generator_frame_cycle.py b/tests/run/generator_frame_cycle.py index d912ff9cc..3789d4c8d 100644 --- a/tests/run/generator_frame_cycle.py +++ b/tests/run/generator_frame_cycle.py @@ -1,6 +1,7 @@ # mode: run # tag: generator +import cython import sys @@ -24,6 +25,9 @@ def test_generator_frame_cycle(): eval('g.throw(ValueError)', {'g': g}) del g + if cython.compiled: + # FIXME: this should not be necessary, but I can't see how to do it... + import gc; gc.collect() return tuple(testit) @@ -53,4 +57,7 @@ def test_generator_frame_cycle_with_outer_exc(): del g assert sys.exc_info()[1] is exc, sys.exc_info() + if cython.compiled: + # FIXME: this should not be necessary, but I can't see how to do it... + import gc; gc.collect() return tuple(testit) |