cpython: 62948164ff94 (original) (raw)
Mercurial > cpython
changeset 103831:62948164ff94 3.6
Merge 3.5 (issue #27906) [#27906]
Yury Selivanov yury@magic.io | |
---|---|
date | Thu, 15 Sep 2016 14:14:48 -0400 |
parents | b368d78432af(current diff)1dcfafed3cb0(diff) |
children | ac13bf1967b5 f2fdb624074a |
files | Lib/asyncio/base_events.py Lib/asyncio/proactor_events.py Lib/asyncio/selector_events.py Misc/NEWS |
diffstat | 6 files changed, 60 insertions(+), 36 deletions(-)[+] [-] Lib/asyncio/base_events.py 2 Lib/asyncio/proactor_events.py 2 Lib/asyncio/selector_events.py 73 Lib/test/test_asyncio/test_base_events.py 2 Lib/test/test_asyncio/test_selector_events.py 14 Misc/NEWS 3 |
line wrap: on
line diff
--- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1035,7 +1035,7 @@ class BaseEventLoop(events.AbstractEvent for sock in sockets: sock.listen(backlog) sock.setblocking(False)
self._start_serving(protocol_factory, sock, ssl, server)[](#l1.7)
self._start_serving(protocol_factory, sock, ssl, server, backlog)[](#l1.8) if self._debug:[](#l1.9) logger.info("%r is serving", server)[](#l1.10) return server[](#l1.11)
--- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -495,7 +495,7 @@ class BaseProactorEventLoop(base_events. self._csock.send(b'\0') def _start_serving(self, protocol_factory, sock,
sslcontext=None, server=None):[](#l2.7)
sslcontext=None, server=None, backlog=100):[](#l2.8)
--- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -162,43 +162,50 @@ class BaseSelectorEventLoop(base_events. exc_info=True) def _start_serving(self, protocol_factory, sock,
sslcontext=None, server=None):[](#l3.7)
sslcontext=None, server=None, backlog=100):[](#l3.8) self.add_reader(sock.fileno(), self._accept_connection,[](#l3.9)
protocol_factory, sock, sslcontext, server)[](#l3.10)
protocol_factory, sock, sslcontext, server, backlog)[](#l3.11)
def _accept_connection(self, protocol_factory, sock,
sslcontext=None, server=None):[](#l3.14)
try:[](#l3.15)
conn, addr = sock.accept()[](#l3.16)
if self._debug:[](#l3.17)
logger.debug("%r got a new connection from %r: %r",[](#l3.18)
server, addr, conn)[](#l3.19)
conn.setblocking(False)[](#l3.20)
except (BlockingIOError, InterruptedError, ConnectionAbortedError):[](#l3.21)
pass # False alarm.[](#l3.22)
except OSError as exc:[](#l3.23)
# There's nowhere to send the error, so just log it.[](#l3.24)
if exc.errno in (errno.EMFILE, errno.ENFILE,[](#l3.25)
errno.ENOBUFS, errno.ENOMEM):[](#l3.26)
# Some platforms (e.g. Linux keep reporting the FD as[](#l3.27)
# ready, so we remove the read handler temporarily.[](#l3.28)
# We'll try again in a while.[](#l3.29)
self.call_exception_handler({[](#l3.30)
'message': 'socket.accept() out of system resource',[](#l3.31)
'exception': exc,[](#l3.32)
'socket': sock,[](#l3.33)
})[](#l3.34)
self.remove_reader(sock.fileno())[](#l3.35)
self.call_later(constants.ACCEPT_RETRY_DELAY,[](#l3.36)
self._start_serving,[](#l3.37)
protocol_factory, sock, sslcontext, server)[](#l3.38)
sslcontext=None, server=None, backlog=100):[](#l3.39)
# This method is only called once for each event loop tick where the[](#l3.40)
# listening socket has triggered an EVENT_READ. There may be multiple[](#l3.41)
# connections waiting for an .accept() so it is called in a loop.[](#l3.42)
# See https://bugs.python.org/issue27906 for more details.[](#l3.43)
for _ in range(backlog):[](#l3.44)
try:[](#l3.45)
conn, addr = sock.accept()[](#l3.46)
if self._debug:[](#l3.47)
logger.debug("%r got a new connection from %r: %r",[](#l3.48)
server, addr, conn)[](#l3.49)
conn.setblocking(False)[](#l3.50)
except (BlockingIOError, InterruptedError, ConnectionAbortedError):[](#l3.51)
# Early exit because the socket accept buffer is empty.[](#l3.52)
return None[](#l3.53)
except OSError as exc:[](#l3.54)
# There's nowhere to send the error, so just log it.[](#l3.55)
if exc.errno in (errno.EMFILE, errno.ENFILE,[](#l3.56)
errno.ENOBUFS, errno.ENOMEM):[](#l3.57)
# Some platforms (e.g. Linux keep reporting the FD as[](#l3.58)
# ready, so we remove the read handler temporarily.[](#l3.59)
# We'll try again in a while.[](#l3.60)
self.call_exception_handler({[](#l3.61)
'message': 'socket.accept() out of system resource',[](#l3.62)
'exception': exc,[](#l3.63)
'socket': sock,[](#l3.64)
})[](#l3.65)
self.remove_reader(sock.fileno())[](#l3.66)
self.call_later(constants.ACCEPT_RETRY_DELAY,[](#l3.67)
self._start_serving,[](#l3.68)
protocol_factory, sock, sslcontext, server,[](#l3.69)
backlog)[](#l3.70)
else:[](#l3.71)
raise # The event loop will catch, log and ignore it.[](#l3.72) else:[](#l3.73)
raise # The event loop will catch, log and ignore it.[](#l3.74)
else:[](#l3.75)
extra = {'peername': addr}[](#l3.76)
accept = self._accept_connection2(protocol_factory, conn, extra,[](#l3.77)
sslcontext, server)[](#l3.78)
self.create_task(accept)[](#l3.79)
extra = {'peername': addr}[](#l3.80)
accept = self._accept_connection2(protocol_factory, conn, extra,[](#l3.81)
sslcontext, server)[](#l3.82)
self.create_task(accept)[](#l3.83)
@coroutine def _accept_connection2(self, protocol_factory, conn, extra,
--- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1634,7 +1634,7 @@ class BaseEventLoopWithSelectorTests(tes self.loop.call_later.assert_called_with(constants.ACCEPT_RETRY_DELAY, # self.loop._start_serving mock.ANY,
MyProto, sock, None, None)[](#l4.7)
MyProto, sock, None, None, mock.ANY)[](#l4.8)
def test_call_coroutine(self): @asyncio.coroutine
--- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -687,6 +687,20 @@ class BaseSelectorEventLoopTests(test_ut selectors.EVENT_WRITE)]) self.loop.remove_writer.assert_called_with(1)
- def test_accept_connection_multiple(self):
sock = mock.Mock()[](#l5.8)
sock.accept.return_value = (mock.Mock(), mock.Mock())[](#l5.9)
backlog = 100[](#l5.10)
# Mock the coroutine generation for a connection to prevent[](#l5.11)
# warnings related to un-awaited coroutines.[](#l5.12)
mock_obj = mock.patch.object[](#l5.13)
with mock_obj(self.loop, '_accept_connection2') as accept2_mock:[](#l5.14)
accept2_mock.return_value = None[](#l5.15)
with mock_obj(self.loop, 'create_task') as task_mock:[](#l5.16)
task_mock.return_value = None[](#l5.17)
self.loop._accept_connection(mock.Mock(), sock, backlog=backlog)[](#l5.18)
self.assertEqual(sock.accept.call_count, backlog)[](#l5.19)
+ class SelectorTransportTests(test_utils.TestCase):