classification
Title: asyncio basic event loop stuck with no tasks scheduled or ready
Type: behavior Stage: resolved
Components: asyncio Versions: Python 3.6
process
Status: closed Resolution: postponed
Dependencies: Superseder:
Assigned To: Nosy List: Sheng Zhong, Windson Yang, asvetlov, yselivanov
Priority: normal Keywords:

Created on 2018-07-19 22:19 by Sheng Zhong, last changed 2018-07-24 16:53 by Sheng Zhong. This issue is now closed.

Messages (3)
msg321969 - (view) Author: Sheng Zhong (Sheng Zhong) Date: 2018-07-19 22:19
An exception is raised and propagates up the call stack without being consumed until the asyncio/events.py:_run function. The exception seemingly doesn't get consumed according to my breakpoint (quite strange and a part of my confusion) but the task does get removed from the next loop cycle as expected. 

However, a subsequent call to the loop's _run_once() gets stuck forever on `event_list = self._selector.select(timeout)` with no tasks in its `_ready` or `_scheduled` queue. 

A snippet of the debug session is below
https://i.imgur.com/YLcU8I6.png 

Shouldn't an event loop with no tasks left exit?
msg321984 - (view) Author: Windson Yang (Windson Yang) * Date: 2018-07-20 06:42
Would you mind adding an example file?
msg322314 - (view) Author: Sheng Zhong (Sheng Zhong) Date: 2018-07-24 16:53
Sorry I'm having trouble extracting a bug-producing portion of the code  but I can describe the different components, what I think the problem was, and how I resolved it.

There is one main coroutine (aka handler) responsible for handling the logic of communicating with a socket (build packet, respond to incoming packet). At the start of this coroutine it launches another coroutine with ensure_future (aka server) that sends to and receives UDP packets from a socket and puts the responses into an `asyncio.queue` for the corresponding transaction. 

When the handler expects a responding packet, it awaits a get from the queue for this transaction. The handler's execution is wrapped in an `async_timeout.timeout`.

The server is a while True loop that gets its packets from an `asyncio.DatagramProtocol` in which its `datagram_received` method feeds an internal server queue. The server awaits packets on its queue and forwards it to a transaction queue when it receives any. There were no timeouts in the server coroutine.

I expected that waiting for a packet through the Protocol would block the server coroutine but not the handler coroutine, but the problem was that the handler timeout never had a chance to be processed. This issue was resolved by putting a timeout in the server coroutine on waiting for a get on its internal queue with `wait_for`.
History
Date User Action Args
2018-07-24 16:53:55Sheng Zhongsetstatus: open -> closed
resolution: postponed
messages: + msg322314

stage: resolved
2018-07-20 06:42:22Windson Yangsetnosy: + Windson Yang
messages: + msg321984
2018-07-19 22:19:35Sheng Zhongcreate