diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 6ad84044adf146..dd82c1d2340261 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -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 diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 7b6d1bce5e460f..5a7df774e60858 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -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') diff --git a/Misc/NEWS.d/next/Library/2025-07-17-16-12-23.gh-issue-136234.VmTxtj.rst b/Misc/NEWS.d/next/Library/2025-07-17-16-12-23.gh-issue-136234.VmTxtj.rst new file mode 100644 index 00000000000000..044a601c9170a1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-07-17-16-12-23.gh-issue-136234.VmTxtj.rst @@ -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`.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: