https://github.com/python/cpython/commit/b2247bb07a5c509030fb66caf25bd33bee5523b5 commit: b2247bb07a5c509030fb66caf25bd33bee5523b5 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: asvetlov <[email protected]> date: 2026-11-04T10:01:10+01:00 summary:
[3.15] gh-161076: Ignore setsockopt(TCP_NODELAY) errors in asyncio (GH-161253) (#161301) gh-161076: Ignore setsockopt(TCP_NODELAY) errors in asyncio (GH-161253) (cherry picked from commit 405f12722cb7631f15d5b6df5825a2262209d9d8) Co-authored-by: Andrew Svetlov <[email protected]> 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 59c61f9ba657a1..a2aa304f868343 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -195,7 +195,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 01529a9a2c1a60..68abcb026ad38e 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -2426,6 +2426,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]
