Skip to content

Commit 05c6fcc

Browse files
committed
bugfix: write to another transport in resume_writing() fails
Fixes #496
1 parent 598b16f commit 05c6fcc

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

tests/test_tcp.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,59 @@ async def runner():
652652
self.assertIsNone(
653653
self.loop.run_until_complete(connection_lost_called))
654654

655+
def test_resume_writing_write_different_transport(self):
656+
loop = self.loop
657+
658+
class P1(asyncio.Protocol):
659+
def __init__(self, t2):
660+
self.t2 = t2
661+
self.paused = False
662+
self.waiter = loop.create_future()
663+
664+
def data_received(self, data):
665+
self.waiter.set_result(data)
666+
667+
def pause_writing(self):
668+
self.paused = True
669+
670+
def resume_writing(self):
671+
self.paused = False
672+
self.t2.write(b'hello')
673+
674+
s1, s2 = socket.socketpair()
675+
s1.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024)
676+
s2.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024)
677+
678+
async def _test(t1, p1, t2):
679+
t1.set_write_buffer_limits(1024, 1023)
680+
681+
# fill s1 up first
682+
t2.pause_reading()
683+
while not p1.paused:
684+
t1.write(b' ' * 1024)
685+
686+
# trigger resume_writing() in _exec_queued_writes() with tight loop
687+
t2.resume_reading()
688+
while p1.paused:
689+
t1.write(b' ')
690+
await asyncio.sleep(0)
691+
692+
# t2.write() in p1.resume_writing() should work fine
693+
data = await asyncio.wait_for(p1.waiter, 5)
694+
self.assertEqual(data, b'hello')
695+
696+
async def test():
697+
t2, _ = await loop.create_connection(asyncio.Protocol, sock=s2)
698+
t1, p1 = await loop.create_connection(lambda: P1(t2), sock=s1)
699+
try:
700+
await _test(t1, p1, t2)
701+
finally:
702+
t1.close()
703+
t2.close()
704+
705+
with s1, s2:
706+
loop.run_until_complete(test())
707+
655708

656709
class Test_UV_TCP(_TestTCP, tb.UVTestCase):
657710

uvloop/loop.pyx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -645,25 +645,17 @@ cdef class Loop:
645645

646646
cdef:
647647
UVStream stream
648-
int queued_len
649648

650-
if UVLOOP_DEBUG:
651-
queued_len = len(self._queued_streams)
649+
streams = list(self._queued_streams)
650+
self._queued_streams.clear()
652651

653-
for pystream in self._queued_streams:
652+
for pystream in streams:
654653
stream = <UVStream>pystream
655654
stream._exec_write()
656655

657-
if UVLOOP_DEBUG:
658-
if len(self._queued_streams) != queued_len:
659-
raise RuntimeError(
660-
'loop._queued_streams are not empty after '
661-
'_exec_queued_writes')
662-
663-
self._queued_streams.clear()
664-
665656
if self.handler_check__exec_writes.running:
666-
self.handler_check__exec_writes.stop()
657+
if len(self._queued_streams) == 0:
658+
self.handler_check__exec_writes.stop()
667659

668660
cdef inline _call_soon(self, object callback, object args, object context):
669661
cdef Handle handle

0 commit comments

Comments
 (0)