Issue 36456: task.cancel unbound recursion if task is deadlocked (original) (raw)
Cancelling a deadlocked group of tasks results in MaximumRecursionError
Inspired by https://stackoverflow.com/questions/55341189/handling-asyncio-deadlocks
Given the following test-asyncio.py:
import asyncio
async def test():
async def f():
await g_task
async def g():
await f_task
f_task = asyncio.create_task(f())
g_task = asyncio.create_task(g())
async def release():
await asyncio.sleep(5)
f_task.cancel()
await asyncio.gather(f_task, g_task, release())
asyncio.run(test())
Results in:
Traceback (most recent call last):
File ".../python3.8/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File ".../python3.8/asyncio/base_events.py", line 589, in run_until_complete
return future.result()
File "test-asyncio.py", line 18, in test
await asyncio.gather(f_task, g_task, release())
File "test-asyncio.py", line 16, in release
f_task.cancel()
RecursionError: maximum recursion depth exceeded while calling a Python object
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test-asyncio.py", line 20, in <module>
asyncio.run(test())
File ".../python3.8/asyncio/runners.py", line 46, in run
_cancel_all_tasks(loop)
File ".../python3.8/asyncio/runners.py", line 59, in _cancel_all_tasks
task.cancel()
RecursionError: maximum recursion depth exceeded while calling a Python object
Exception in default exception handler
Traceback (most recent call last):
File ".../python3.8/asyncio/base_events.py", line 1644, in call_exception_handler
self.default_exception_handler(context)
File ".../python3.8/asyncio/base_events.py", line 1615, in default_exception_handler
value = repr(value)
File ".../python3.8/asyncio/base_tasks.py", line 21, in _task_repr_info
info.insert(3, f'wait_for={task._fut_waiter!r}')
File ".../python3.8/asyncio/base_tasks.py", line 21, in _task_repr_info
info.insert(3, f'wait_for={task._fut_waiter!r}')
File ".../python3.8/asyncio/base_tasks.py", line 21, in _task_repr_info
info.insert(3, f'wait_for={task._fut_waiter!r}')
[Previous line repeated 326 more times]
File ".../python3.8/asyncio/base_tasks.py", line 9, in _task_repr_info
info = base_futures._future_repr_info(task)
File ".../python3.8/asyncio/base_futures.py", line 57, in _future_repr_info
info.append(_format_callbacks(future._callbacks))
File ".../python3.8/asyncio/base_futures.py", line 36, in _format_callbacks
cb = '{}, {}'.format(format_cb(cb[0][0]), format_cb(cb[1][0]))
File ".../python3.8/asyncio/base_futures.py", line 31, in format_cb
return format_helpers._format_callback_source(callback, ())
File ".../python3.8/asyncio/format_helpers.py", line 23, in _format_callback_source
func_repr = _format_callback(func, args, None)
File ".../python3.8/asyncio/format_helpers.py", line 56, in _format_callback
func_repr += _format_args_and_kwargs(args, kwargs)
File ".../python3.8/asyncio/format_helpers.py", line 41, in _format_args_and_kwargs
return '({})'.format(', '.join(items))
RecursionError: maximum recursion depth exceeded while calling a Python object
Exception in default exception handler
Traceback (most recent call last):
File ".../python3.8/asyncio/base_events.py", line 1644, in call_exception_handler
self.default_exception_handler(context)
File ".../python3.8/asyncio/base_events.py", line 1615, in default_exception_handler
value = repr(value)
File ".../python3.8/asyncio/base_tasks.py", line 21, in _task_repr_info
info.insert(3, f'wait_for={task._fut_waiter!r}')
File ".../python3.8/asyncio/base_tasks.py", line 21, in _task_repr_info
info.insert(3, f'wait_for={task._fut_waiter!r}')
File ".../python3.8/asyncio/base_tasks.py", line 21, in _task_repr_info
info.insert(3, f'wait_for={task._fut_waiter!r}')
[Previous line repeated 326 more times]
File ".../python3.8/asyncio/base_tasks.py", line 9, in _task_repr_info
info = base_futures._future_repr_info(task)
File ".../python3.8/asyncio/base_futures.py", line 57, in _future_repr_info
info.append(_format_callbacks(future._callbacks))
File ".../python3.8/asyncio/base_futures.py", line 36, in _format_callbacks
cb = '{}, {}'.format(format_cb(cb[0][0]), format_cb(cb[1][0]))
File ".../python3.8/asyncio/base_futures.py", line 31, in format_cb
return format_helpers._format_callback_source(callback, ())
File ".../python3.8/asyncio/format_helpers.py", line 23, in _format_callback_source
func_repr = _format_callback(func, args, None)
File ".../python3.8/asyncio/format_helpers.py", line 56, in _format_callback
func_repr += _format_args_and_kwargs(args, kwargs)
File ".../python3.8/asyncio/format_helpers.py", line 41, in _format_args_and_kwargs
return '({})'.format(', '.join(items))
RecursionError: maximum recursion depth exceeded while calling a Python object