Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Lib/asyncio/selector_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
19 changes: 19 additions & 0 deletions Lib/test/test_asyncio/test_selector_events.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Tests for selector_events.py"""

import collections
import errno
import selectors
import socket
import sys
Expand Down Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Loading