https://github.com/python/cpython/commit/6081d166f191752c4dd17b5c6037bcf446c8dfb9
commit: 6081d166f191752c4dd17b5c6037bcf446c8dfb9
branch: main
author: Timofei <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-07-12T15:38:32+05:30
summary:

gh-151615: Avoid repeated reschedule in asyncio _accept_connection (#151616)

Co-authored-by: Kumar Aditya <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-06-18-00-39-58.gh-issue-151615.PBsCE1.rst
M Lib/asyncio/selector_events.py
M Lib/test/test_asyncio/test_selector_events.py

diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index 4fa4dd5a885236..492dfcb19dafe2 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -206,6 +206,7 @@ def _accept_connection(
                                     protocol_factory, sock, sslcontext, server,
                                     backlog, ssl_handshake_timeout,
                                     ssl_shutdown_timeout, context)
+                    return
                 else:
                     raise  # The event loop will catch, log and ignore it.
             else:
diff --git a/Lib/test/test_asyncio/test_selector_events.py 
b/Lib/test/test_asyncio/test_selector_events.py
index 76ba39019e3663..cf46c13fa5e1f3 100644
--- a/Lib/test/test_asyncio/test_selector_events.py
+++ b/Lib/test/test_asyncio/test_selector_events.py
@@ -1,6 +1,7 @@
 """Tests for selector_events.py"""
 
 import collections
+import errno
 import selectors
 import socket
 import sys
@@ -402,6 +403,24 @@ def mock_sock_accept():
         self.loop.run_until_complete(asyncio.sleep(0))
         self.assertEqual(sock.accept.call_count, backlog + 1)
 
+    def test_accept_connection_reschedules_once_on_resource_error(self):
+        # When accept() fails with a resource error (EMFILE), 
_accept_connection
+        # re-runs the error branch backlog+1 times, logging and rescheduling
+        # _start_serving once per iteration. With early return after first
+        # exception we avoid this behaviour
+        sock = mock.Mock()
+        sock.accept.side_effect = OSError(errno.EMFILE, 'too many open files')
+
+        self.loop.call_exception_handler = mock.Mock()
+        self.loop._remove_reader = mock.Mock()
+        self.loop.call_later = mock.Mock()
+
+        self.loop._accept_connection(mock.Mock(), sock, backlog=100)
+
+        self.assertEqual(sock.accept.call_count, 1)
+        self.assertEqual(self.loop.call_exception_handler.call_count, 1)
+        self.assertEqual(self.loop.call_later.call_count, 1)
+
 class SelectorTransportTests(test_utils.TestCase):
 
     def setUp(self):
diff --git 
a/Misc/NEWS.d/next/Library/2026-06-18-00-39-58.gh-issue-151615.PBsCE1.rst 
b/Misc/NEWS.d/next/Library/2026-06-18-00-39-58.gh-issue-151615.PBsCE1.rst
new file mode 100644
index 00000000000000..1d08dbacef1f79
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-18-00-39-58.gh-issue-151615.PBsCE1.rst
@@ -0,0 +1,2 @@
+Fix :mod:`asyncio` servers repeatedly logging and rescheduling on a single
+event loop iteration when ``accept()`` fails with a resource errors.

_______________________________________________
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