New submission from Dmitry Malinovsky:

When there is a huge amount of `writer.write` calls followed by `await 
writer.drain()` on a non-paused channel, and there are no other coroutine 
switches, `await writer.drain()` immediately returns without a switch. This is 
because `asyncio.stream.FlowControlMixin._drain_helper` do not `yield` or 
`yield from` on a non-paused stream.

Use-case: AMQP basic.publish method, for which the broker (rabbitmq) do not 
send any replies back. Trying to publish 4k messages results in the following 
warnings (PYTHONASYNCIODEBUG env variable is set):
`Executing <Handle <TaskWakeupMethWrapper object at 0x1106fde28>(<Future 
finis...events.py:275>) created at 
/Users/malinoff/Projects/ideas/amqproto/amqproto/channel.py:85> took 2.371 
seconds`
2.371 seconds is the time spent on 4k `basic_publish` calls.

You can find the test itself on github: 
https://github.com/malinoff/amqproto/blob/master/tests/stress/test_4k_msgs.py#L11-L12

An easy fix would be to replace return 
(https://github.com/python/cpython/blob/master/Lib/asyncio/streams.py#L206) 
with yield (and but the code below under the else clause; I'm willing to 
prepare a pull request), but maybe I'm missing something and such behavior is 
intentional?

----------
components: asyncio
messages: 299610
nosy: Dmitry Malinovsky, yselivanov
priority: normal
severity: normal
status: open
title: asyncio.stream.FlowControlMixin._drain_helper may lead to a blocking 
behavior
versions: Python 3.5, Python 3.6, Python 3.7

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue31096>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to