mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
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.
This commit is contained in:
parent
909b5714e1
commit
7c30d12bd5
7 changed files with 130 additions and 23 deletions
|
@ -536,9 +536,42 @@ class BaseTaskTests:
|
|||
self.assertEqual((type(chained), chained.args),
|
||||
(KeyError, (3,)))
|
||||
|
||||
task = self.new_task(loop, run())
|
||||
loop.run_until_complete(task)
|
||||
loop.close()
|
||||
try:
|
||||
task = self.new_task(loop, run())
|
||||
loop.run_until_complete(task)
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
def test_exception_chaining_after_await_with_context_cycle(self):
|
||||
# Check trying to create an exception context cycle:
|
||||
# https://bugs.python.org/issue40696
|
||||
has_cycle = None
|
||||
loop = asyncio.new_event_loop()
|
||||
self.set_event_loop(loop)
|
||||
|
||||
async def process_exc(exc):
|
||||
raise exc
|
||||
|
||||
async def run():
|
||||
nonlocal has_cycle
|
||||
try:
|
||||
raise KeyError('a')
|
||||
except Exception as exc:
|
||||
task = self.new_task(loop, process_exc(exc))
|
||||
try:
|
||||
await task
|
||||
except BaseException as exc:
|
||||
has_cycle = (exc is exc.__context__)
|
||||
# Prevent a hang if has_cycle is True.
|
||||
exc.__context__ = None
|
||||
|
||||
try:
|
||||
task = self.new_task(loop, run())
|
||||
loop.run_until_complete(task)
|
||||
finally:
|
||||
loop.close()
|
||||
# This also distinguishes from the initial has_cycle=None.
|
||||
self.assertEqual(has_cycle, False)
|
||||
|
||||
def test_cancel(self):
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue