Description
Bug report
Bug description:
Thanks for taking the time to look at this issue.
Recently I've been running into a rare and insidious race condition that can result in a deadlock. The condition triggers when asyncio debugging is enabled (PYTHONASYNCIODEBUG=1
), and a slow callback is encountered:
cpython/Lib/asyncio/base_events.py
Lines 1899 to 1901 in 9e9c71d
We first encountered the issue during our test runs, where it would occur probably approximately 1 out of 4000 times the above message was printed.
The deadlock is actually some form of "livelock", where the interpreter appears to be frozen, but CPU usage is stuck at 100%. The stack trace looks similar to a recursion bug; however it doesn't seem to descend far enough to trigger a RecursionError
, so it survives as an infinite loop.
It took me weeks to track it down, and in the end I was only able to get the stack trace by attaching to the frozen python process with gdb
:
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 634, in run_until_complete
self.run_forever()
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 601, in run_forever
self._run_once()
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 1901, in _run_once
_format_handle(handle), dt)
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 78, in _format_handle
return repr(cb.__self__)
File "/usr/local/lib/python3.9/asyncio/base_tasks.py", line 21, in _task_repr_info
info.insert(3, f'wait_for={task._fut_waiter!r}')
File "/usr/local/lib/python3.9/asyncio/base_futures.py", line 76, in _future_repr_info
info.append(_format_callbacks(future._callbacks))
File "/usr/local/lib/python3.9/asyncio/base_futures.py", line 37, in _format_callbacks
cb = '{}, {}'.format(format_cb(cb[0][0]), format_cb(cb[1][0]))
File "/usr/local/lib/python3.9/asyncio/base_futures.py", line 32, in format_cb
return format_helpers._format_callback_source(callback, ())
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 23, in _format_callback_source
func_repr = _format_callback(func, args, None)
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 47, in _format_callback
return _format_callback(func.func, func.args, func.keywords, suffix)
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 56, in _format_callback
func_repr += _format_args_and_kwargs(args, kwargs)
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 40, in _format_args_and_kwargs
items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items())
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 40, in <genexpr>
items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items())
File "/usr/local/lib/python3.9/reprlib.py", line 52, in repr
return self.repr1(x, self.maxlevel)
File "/usr/local/lib/python3.9/reprlib.py", line 60, in repr1
return getattr(self, 'repr_' + typename)(x, level)
File "/usr/local/lib/python3.9/reprlib.py", line 103, in repr_deque
return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque)
File "/usr/local/lib/python3.9/reprlib.py", line 71, in _repr_iterable
pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)]
File "/usr/local/lib/python3.9/reprlib.py", line 71, in <listcomp>
pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)]
File "/usr/local/lib/python3.9/reprlib.py", line 62, in repr1
return self.repr_instance(x, level)
File "/usr/local/lib/python3.9/reprlib.py", line 139, in repr_instance
s = builtins.repr(x)
File "/usr/local/lib/python3.9/collections/__init__.py", line 458, in __repr__
return self.__class__.__name__ + repr_fmt % self
...repeats ~40 times
return self.__class__.__name__ + repr_fmt % self
File "/usr/local/lib/python3.9/asyncio/base_futures.py", line 76, in _future_repr_info
info.append(_format_callbacks(future._callbacks))
File "/usr/local/lib/python3.9/asyncio/base_futures.py", line 37, in _format_callbacks
cb = '{}, {}'.format(format_cb(cb[0][0]), format_cb(cb[1][0]))
File "/usr/local/lib/python3.9/asyncio/base_futures.py", line 32, in format_cb
return format_helpers._format_callback_source(callback, ())
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 23, in _format_callback_source
func_repr = _format_callback(func, args, None)
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 47, in _format_callback
return _format_callback(func.func, func.args, func.keywords, suffix)
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 56, in _format_callback
func_repr += _format_args_and_kwargs(args, kwargs)
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 40, in _format_args_and_kwargs
items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items())
File "/usr/local/lib/python3.9/asyncio/format_helpers.py", line 40, in <genexpr>
items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items())
File "/usr/local/lib/python3.9/reprlib.py", line 52, in repr
return self.repr1(x, self.maxlevel)
File "/usr/local/lib/python3.9/reprlib.py", line 62, in repr1
return self.repr_instance(x, level)
File "/usr/local/lib/python3.9/reprlib.py", line 139, in repr_instance
s = builtins.repr(x)
File "/usr/local/lib/python3.9/collections/__init__.py", line 458, in __repr__
return self.__class__.__name__ + repr_fmt % self
File "<string>", line 1, in <module>
Full traceback:
python_traceback.txt
CPython versions tested on:
3.9
Operating systems tested on:
Linux
Metadata
Metadata
Assignees
Projects
Status