https://github.com/python/cpython/commit/405f12722cb7631f15d5b6df5825a2262209d9d8
commit: 405f12722cb7631f15d5b6df5825a2262209d9d8
branch: main
author: Andrew Svetlov <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-11-04T11:25:12+05:30
summary:

gh-161076: Ignore setsockopt(TCP_NODELAY) errors in asyncio (#161253)

files:
A Misc/NEWS.d/next/Library/2026-11-03-12-00-00.gh-issue-161076.nOdLy1.rst
M Lib/asyncio/base_events.py
M Lib/test/test_asyncio/test_base_events.py

diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 861210775347ae..5d295bc3fb9b5c 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -196,7 +196,13 @@ def _set_nodelay(sock):
         if (sock.family in {socket.AF_INET, socket.AF_INET6} and
                 sock.type == socket.SOCK_STREAM and
                 sock.proto == socket.IPPROTO_TCP):
-            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+            try:
+                sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+            except OSError:
+                # TCP_NODELAY is only a latency optimization.  It can fail
+                # on a connection already reset by the peer (e.g. EINVAL
+                # on macOS); the error will surface on the next I/O.
+                pass
 else:
     def _set_nodelay(sock):
         pass
diff --git a/Lib/test/test_asyncio/test_base_events.py 
b/Lib/test/test_asyncio/test_base_events.py
index e11f77ef10c0c9..0c54b64efad7e2 100644
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -2517,6 +2517,17 @@ def test_set_nodelay(self):
             sock.setblocking(False)
             self.check_set_nodelay(sock)
 
+    @unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'),
+                         'need socket.TCP_NODELAY')
+    def test_set_nodelay_error(self):
+        # gh-161076: a failing setsockopt() must not break transport creation.
+        sock = mock.Mock(family=socket.AF_INET, type=socket.SOCK_STREAM,
+                         proto=socket.IPPROTO_TCP)
+        sock.setsockopt.side_effect = OSError(errno.EINVAL, 'Invalid argument')
+        base_events._set_nodelay(sock)
+        sock.setsockopt.assert_called_once_with(
+            socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+
 
 
 if __name__ == '__main__':
diff --git 
a/Misc/NEWS.d/next/Library/2026-11-03-12-00-00.gh-issue-161076.nOdLy1.rst 
b/Misc/NEWS.d/next/Library/2026-11-03-12-00-00.gh-issue-161076.nOdLy1.rst
new file mode 100644
index 00000000000000..bc286d0a676c02
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-11-03-12-00-00.gh-issue-161076.nOdLy1.rst
@@ -0,0 +1,5 @@
+Fix :mod:`asyncio` leaving a half-created transport registered with the
+event loop and the server when setting ``TCP_NODELAY`` on a socket fails.
+Such a failure could make :meth:`asyncio.Server.wait_closed` hang and
+prevent new connections from being served.  Errors from
+``setsockopt(TCP_NODELAY)`` are now ignored.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to