erdewit / nest_asyncio

Patch asyncio to allow nested event loops
BSD 2-Clause "Simplified" License
693 stars 79 forks source link

nested tasks causing deadlock? #66

Closed Androidown closed 2 years ago

Androidown commented 2 years ago

question

The following code will lead to a infinite polling in both windows and linux. I'm quite new to nested asyncio so I want to know if it is a bug or not.

code

import asyncio
import nest_asyncio

nest_asyncio.apply()

async def nested(t):
    asyncio.run(t)
    print('finished')

async def main():
    t = asyncio.create_task(nested(asyncio.sleep(1)))
    asyncio.run(nested(t))   # deadlock?
    # await nested(t)   # finished normally

asyncio.run(main())

enviroment

cpython 3.8.10 nest_asyncio==1.5.4

stack

(gdb) py-bt-full
#6 Frame 0x1987b90, for file /usr/lib/python3.8/selectors.py, line 468, in select (self=<EpollSelector(_fd_to_key={7: <SelectorKey at remote 0x7f635d6b7a40>}, _map=<_SelectorMapping(_selector=<...>) at remote 0x7f635d6a8df0>, _selector=<select.epoll at remote 0x7f635d6b4150>) at remote 0x7f635d6a8d90>, timeout=-1, max_ev=1, ready=[])
    fd_event_list = self._selector.poll(timeout, max_ev)
#12 Frame 0x7f635d6c4040, for file /usr/local/lib/python3.8/dist-packages/nest_asyncio.py, line 1122, in _run_once (self=<_UnixSelectorEventLoop(_timer_cancelled_count=1, _closed=False, _stopping=False, _ready=<collections.deque at remote 0x7f635d6aabe0>, _scheduled=[], _default_executor=None, _internal_fds=1, _thread_id=140064757851968, _clock_resolution=<float at remote 0x7f635d7ddd10>, _exception_handler=None, _debug=False, slow_callback_duration=<float at remote 0x7f635ddafed0>, _current_handle=None, _task_factory=None, _coroutine_origin_tracking_enabled=False, _coroutine_origin_tracking_saved_depth=None, _asyncgens=<WeakSet(data=set(), _remove=<function at remote 0x7f635d6b9a60>, _pending_removals=[], _iterating=set()) at remote 0x7f635d6a8d30>, _asyncgens_shutdown_called=False, _selector=<EpollSelector(_fd_to_key={7: <SelectorKey at remote 0x7f635d6b7a40>}, _map=<_SelectorMapping(_selector=<...>) at remote 0x7f635d6a8df0>, _selector=<select.epoll at remote 0x7f635d6b4150>) at remote 0x7f635d6a8d90>, _ssock=...(truncated)
#18 Frame 0x7f635d6c1be0, for file /usr/local/lib/python3.8/dist-packages/nest_asyncio.py, line 75, in run_until_complete (self=<_UnixSelectorEventLoop(_timer_cancelled_count=1, _closed=False, _stopping=False, _ready=<collections.deque at remote 0x7f635d6aabe0>, _scheduled=[], _default_executor=None, _internal_fds=1, _thread_id=140064757851968, _clock_resolution=<float at remote 0x7f635d7ddd10>, _exception_handler=None, _debug=False, slow_callback_duration=<float at remote 0x7f635ddafed0>, _current_handle=None, _task_factory=None, _coroutine_origin_tracking_enabled=False, _coroutine_origin_tracking_saved_depth=None, _asyncgens=<WeakSet(data=set(), _remove=<function at remote 0x7f635d6b9a60>, _pending_removals=[], _iterating=set()) at remote 0x7f635d6a8d30>, _asyncgens_shutdown_called=False, _selector=<EpollSelector(_fd_to_key={7: <SelectorKey at remote 0x7f635d6b7a40>}, _map=<_SelectorMapping(_selector=<...>) at remote 0x7f635d6a8df0>, _selector=<select.epoll at remote 0x7f635d6b4150>) at remote 0x7f635d6a8d90>, ...(truncated)
    self._run_once()
#24 Frame 0x19c9e50, for file /usr/local/lib/python3.8/dist-packages/nest_asyncio.py, line 38, in run (main=<Task(_loop=<_UnixSelectorEventLoop(_timer_cancelled_count=1, _closed=False, _stopping=False, _ready=<collections.deque at remote 0x7f635d6aabe0>, _scheduled=[], _default_executor=None, _internal_fds=1, _thread_id=140064757851968, _clock_resolution=<float at remote 0x7f635d7ddd10>, _exception_handler=None, _debug=False, slow_callback_duration=<float at remote 0x7f635ddafed0>, _current_handle=None, _task_factory=None, _coroutine_origin_tracking_enabled=False, _coroutine_origin_tracking_saved_depth=None, _asyncgens=<WeakSet(data=set(), _remove=<function at remote 0x7f635d6b9a60>, _pending_removals=[], _iterating=set()) at remote 0x7f635d6a8d30>, _asyncgens_shutdown_called=False, _selector=<EpollSelector(_fd_to_key={7: <SelectorKey at remote 0x7f635d6b7a40>}, _map=<_SelectorMapping(_selector=<...>) at remote 0x7f635d6a8df0>, _selector=<select.epoll at remote 0x7f635d6b4150>) at remote 0x7f635d6a8d90>, _ssock=<...(truncated)
    return loop.run_until_complete(task)
erdewit commented 2 years ago

To call async code from async code you can just use await, this project is for calling async code from sync code.

Btw it looks like in the snippet there's a circular dependency, with two tasks waiting on the other to finish.