From 7c30d12bd5359b0f66c4fbc98aa055398bcc8a7e Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Fri, 22 May 2020 13:33:27 -0700 Subject: bpo-40696: Fix a hang that can arise after gen.throw() (GH-20287) This updates _PyErr_ChainStackItem() to use _PyErr_SetObject() instead of _PyErr_ChainExceptions(). This prevents a hang in certain circumstances because _PyErr_SetObject() performs checks to prevent cycles in the exception context chain while _PyErr_ChainExceptions() doesn't. --- Lib/test/test_generators.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'Lib/test/test_generators.py') diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 87cc2dfc8c..bf482213c1 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -371,6 +371,32 @@ class GeneratorThrowTest(unittest.TestCase): context = cm.exception.__context__ self.assertEqual((type(context), context.args), (KeyError, ('a',))) + def test_exception_context_with_yield_from_with_context_cycle(self): + # Check trying to create an exception context cycle: + # https://bugs.python.org/issue40696 + has_cycle = None + + def f(): + yield + + def g(exc): + nonlocal has_cycle + try: + raise exc + except Exception: + try: + yield from f() + except Exception as exc: + has_cycle = (exc is exc.__context__) + yield + + exc = KeyError('a') + gen = g(exc) + gen.send(None) + gen.throw(exc) + # This also distinguishes from the initial has_cycle=None. + self.assertEqual(has_cycle, False) + def test_throw_after_none_exc_type(self): def g(): try: -- cgit v1.2.1