Fix retransmit bug for large messages causing message corruption
Logic bug: We are looping over segments sent by the C++ library and sending them over a python transport. If the last message is larger than the transport pause threshold, this causes the transport to pause us. In that case, we forget to increment the current write_index, causing us to retransmit the same message in an infinite loop. This is a serious bug, because it causes messages to become corrupted.
This commit is contained in:
committed by
Jacob Alexander
parent
302a96d84d
commit
a30fd77a1c
@@ -2371,6 +2371,7 @@ cdef class _AsyncIoStream:
|
|||||||
elif self.protocol.transport is not None and hasattr(self.protocol.transport, "close"):
|
elif self.protocol.transport is not None and hasattr(self.protocol.transport, "close"):
|
||||||
self.protocol.transport.close()
|
self.protocol.transport.close()
|
||||||
# Call connection_lost immediately, instead of waiting for the transport to do it.
|
# Call connection_lost immediately, instead of waiting for the transport to do it.
|
||||||
|
# TODO: This might be a questionable thing to do...
|
||||||
self.protocol.connection_lost("Stream is closing")
|
self.protocol.connection_lost("Stream is closing")
|
||||||
|
|
||||||
async def wait_closed(self):
|
async def wait_closed(self):
|
||||||
@@ -2558,15 +2559,15 @@ cdef class _PyAsyncIoStreamProtocol(DummyBaseClass, asyncio.BufferedProtocol):
|
|||||||
self.read_reset()
|
self.read_reset()
|
||||||
|
|
||||||
cdef write_loop(self):
|
cdef write_loop(self):
|
||||||
if not self.write_in_progress: return
|
if self.write_paused or not self.write_in_progress: return
|
||||||
cdef const ArrayPtr[const uint8_t]* piece
|
cdef const ArrayPtr[const uint8_t]* piece
|
||||||
for i in range(self.write_index, self.write_pieces.size()):
|
for i in range(self.write_index, self.write_pieces.size()):
|
||||||
if self.write_paused:
|
|
||||||
self.write_index = i
|
|
||||||
break
|
|
||||||
piece = &self.write_pieces[i]
|
piece = &self.write_pieces[i]
|
||||||
view = memoryview.PyMemoryView_FromMemory(<char*>piece.begin(), piece.size(), buffer.PyBUF_READ)
|
view = memoryview.PyMemoryView_FromMemory(<char*>piece.begin(), piece.size(), buffer.PyBUF_READ)
|
||||||
self.transport.write(view)
|
self.transport.write(view)
|
||||||
|
if self.write_paused:
|
||||||
|
self.write_index = i+1
|
||||||
|
break
|
||||||
if not self.write_paused:
|
if not self.write_paused:
|
||||||
self.write_fulfiller.fulfill()
|
self.write_fulfiller.fulfill()
|
||||||
self.write_reset()
|
self.write_reset()
|
||||||
|
|||||||
Reference in New Issue
Block a user