]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-136234: Fix `SelectorSocketTransport.writelines` to be robust to connection...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 7 Oct 2025 17:57:57 +0000 (19:57 +0200)
committerGitHub <noreply@github.com>
Tue, 7 Oct 2025 17:57:57 +0000 (17:57 +0000)
[3.14] gh-136234: Fix `SelectorSocketTransport.writelines` to be robust to connection loss (GH-136743) (GH-138702)
(cherry picked from commit 5cd6cfe4cf6770b9424bb23f8c7c661f7a3db7b0)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Lib/asyncio/selector_events.py
Lib/test/test_asyncio/test_selector_events.py
Misc/NEWS.d/next/Library/2025-07-17-16-12-23.gh-issue-136234.VmTxtj.rst [new file with mode: 0644]

index df5b1e49240fe0867b8cd26a63386eb09b696f0d..8701467d41322ab13fd485969715ed6adbc7748c 100644 (file)
@@ -1170,6 +1170,13 @@ class _SelectorSocketTransport(_SelectorTransport):
             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
index 1e7761ee38d76faf660760b075997e13ff12becc..bfb347e4a8cf2e3ab729c98efc2ad87f709a7ba1 100644 (file)
@@ -817,6 +817,22 @@ class SelectorSocketTransportTests(test_utils.TestCase):
         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 (file)
index 0000000..044a601
--- /dev/null
@@ -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`.