diff options
author | Guido van Rossum <guido@dropbox.com> | 2013-11-01 21:12:50 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@dropbox.com> | 2013-11-01 21:12:50 (GMT) |
commit | 3317a1325385a6b7a4a208e0d00c43e9e8ac562e (patch) | |
tree | 495eec1e8c8d00e1e8238ca4bd2f1d1ff58bb77a /Lib/asyncio | |
parent | 2b8fc303ad60894bf76b76f82e774b2c7e9f1702 (diff) | |
download | cpython-3317a1325385a6b7a4a208e0d00c43e9e8ac562e.zip cpython-3317a1325385a6b7a4a208e0d00c43e9e8ac562e.tar.gz cpython-3317a1325385a6b7a4a208e0d00c43e9e8ac562e.tar.bz2 |
asyncio: Pause accepting whenever accept() returns certain errors. Fixes asyncio issue #78.
Diffstat (limited to 'Lib/asyncio')
-rw-r--r-- | Lib/asyncio/constants.py | 5 | ||||
-rw-r--r-- | Lib/asyncio/selector_events.py | 21 |
2 files changed, 19 insertions, 7 deletions
diff --git a/Lib/asyncio/constants.py b/Lib/asyncio/constants.py index 79c3b93..f9e1232 100644 --- a/Lib/asyncio/constants.py +++ b/Lib/asyncio/constants.py @@ -1,4 +1,7 @@ """Constants.""" - +# After the connection is lost, log warnings after this many write()s. LOG_THRESHOLD_FOR_CONNLOST_WRITES = 5 + +# Seconds to wait before retrying accept(). +ACCEPT_RETRY_DELAY = 1 diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index c296dcc..f7bc61a 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -5,6 +5,7 @@ also includes support for signal handling, see the unix_events sub-module. """ import collections +import errno import socket try: import ssl @@ -98,15 +99,23 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): try: conn, addr = sock.accept() conn.setblocking(False) - except (BlockingIOError, InterruptedError): + except (BlockingIOError, InterruptedError, ConnectionAbortedError): pass # False alarm. - except Exception: - # Bad error. Stop serving. - self.remove_reader(sock.fileno()) - sock.close() + except OSError as exc: # There's nowhere to send the error, so just log it. # TODO: Someone will want an error handler for this. - logger.exception('Accept failed') + if exc.errno in (errno.EMFILE, errno.ENFILE, + errno.ENOBUFS, errno.ENOMEM): + # Some platforms (e.g. Linux keep reporting the FD as + # ready, so we remove the read handler temporarily. + # We'll try again in a while. + logger.exception('Accept out of system resource (%s)', exc) + self.remove_reader(sock.fileno()) + self.call_later(constants.ACCEPT_RETRY_DELAY, + self._start_serving, + protocol_factory, sock, ssl, server) + else: + raise # The event loop will catch, log and ignore it. else: if ssl: self._make_ssl_transport( |