[3.14] gh-136234: Fix SelectorSocketTransport.writelines to be robust to connection loss (GH-136743) (#138702)

This commit is contained in:
Kumar Aditya 2025-10-07 23:06:04 +05:30 committed by GitHub
parent de84d09050
commit 5cd6cfe4cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 25 additions and 0 deletions

View file

@ -1174,6 +1174,13 @@ def writelines(self, list_of_data):
raise RuntimeError('unable to writelines; sendfile is in progress')
if not list_of_data:
return
if self._conn_lost:
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
logger.warning('socket.send() raised exception.')
self._conn_lost += 1
return
self._buffer.extend([memoryview(data) for data in list_of_data])
self._write_ready()
# If the entire buffer couldn't be written, register a write handler

View file

@ -854,6 +854,22 @@ def test_writelines_pauses_protocol(self):
self.assertTrue(self.sock.send.called)
self.assertTrue(self.loop.writers)
def test_writelines_after_connection_lost(self):
# GH-136234
transport = self.socket_transport()
self.sock.send = mock.Mock()
self.sock.send.side_effect = ConnectionResetError
transport.write(b'data1') # Will fail immediately, causing connection lost
transport.writelines([b'data2'])
self.assertFalse(transport._buffer)
self.assertFalse(self.loop.writers)
test_utils.run_briefly(self.loop) # Allow _call_connection_lost to run
transport.writelines([b'data2'])
self.assertFalse(transport._buffer)
self.assertFalse(self.loop.writers)
@unittest.skipUnless(selector_events._HAS_SENDMSG, 'no sendmsg')
def test_write_sendmsg_full(self):
data = memoryview(b'data')

View file

@ -0,0 +1,2 @@
Fix :meth:`asyncio.WriteTransport.writelines` to be robust to connection
failure, by using the same behavior as :meth:`~asyncio.WriteTransport.write`.