summaryrefslogtreecommitdiffstats
path: root/Lib/asyncio
diff options
context:
space:
mode:
authorGuido van Rossum <guido@dropbox.com>2013-11-01 21:12:50 (GMT)
committerGuido van Rossum <guido@dropbox.com>2013-11-01 21:12:50 (GMT)
commit3317a1325385a6b7a4a208e0d00c43e9e8ac562e (patch)
tree495eec1e8c8d00e1e8238ca4bd2f1d1ff58bb77a /Lib/asyncio
parent2b8fc303ad60894bf76b76f82e774b2c7e9f1702 (diff)
downloadcpython-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.py5
-rw-r--r--Lib/asyncio/selector_events.py21
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(