summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-01-29 14:09:43 +0100
committerVictor Stinner <victor.stinner@gmail.com>2015-01-29 14:09:43 +0100
commit801fb32b5fe761eda5152b332f6fd50d76bfde25 (patch)
treece30517af86968547404994eeb3af0a7ec528818
parent3953d223af2155670d3fa4d1c3e74ca34dc0e058 (diff)
downloadtrollius-801fb32b5fe761eda5152b332f6fd50d76bfde25.tar.gz
Fix BaseSelectorEventLoop._accept_connection()
* Close the transport on error * In debug mode, log errors using call_exception_handler()
-rw-r--r--asyncio/selector_events.py44
-rw-r--r--tests/test_events.py37
2 files changed, 62 insertions, 19 deletions
diff --git a/asyncio/selector_events.py b/asyncio/selector_events.py
index 3195f62..9147832 100644
--- a/asyncio/selector_events.py
+++ b/asyncio/selector_events.py
@@ -22,6 +22,7 @@ from . import futures
from . import selectors
from . import transports
from . import sslproto
+from .coroutines import coroutine
from .log import logger
@@ -181,16 +182,47 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
else:
raise # The event loop will catch, log and ignore it.
else:
+ extra = {'peername': addr}
+ accept = self._accept_connection2(protocol_factory, conn, extra,
+ sslcontext, server)
+ self.create_task(accept)
+
+ @coroutine
+ def _accept_connection2(self, protocol_factory, conn, extra,
+ sslcontext=None, server=None):
+ protocol = None
+ transport = None
+ try:
protocol = protocol_factory()
+ waiter = futures.Future(loop=self)
if sslcontext:
- self._make_ssl_transport(
- conn, protocol, sslcontext,
- server_side=True, extra={'peername': addr}, server=server)
+ transport = self._make_ssl_transport(
+ conn, protocol, sslcontext, waiter=waiter,
+ server_side=True, extra=extra, server=server)
else:
- self._make_socket_transport(
- conn, protocol , extra={'peername': addr},
+ transport = self._make_socket_transport(
+ conn, protocol, waiter=waiter, extra=extra,
server=server)
- # It's now up to the protocol to handle the connection.
+
+ try:
+ yield from waiter
+ except:
+ transport.close()
+ raise
+
+ # It's now up to the protocol to handle the connection.
+ except Exception as exc:
+ if self.get_debug():
+ context = {
+ 'message': ('Error on transport creation '
+ 'for incoming connection'),
+ 'exception': exc,
+ }
+ if protocol is not None:
+ context['protocol'] = protocol
+ if transport is not None:
+ context['transport'] = transport
+ self.call_exception_handler(context)
def add_reader(self, fd, callback, *args):
"""Add a reader callback."""
diff --git a/tests/test_events.py b/tests/test_events.py
index a38c90e..12af62b 100644
--- a/tests/test_events.py
+++ b/tests/test_events.py
@@ -886,13 +886,18 @@ class EventLoopTestsMixin:
if hasattr(sslcontext_client, 'check_hostname'):
sslcontext_client.check_hostname = True
+
# no CA loaded
f_c = self.loop.create_connection(MyProto, host, port,
ssl=sslcontext_client)
- with test_utils.disable_logger():
- with self.assertRaisesRegex(ssl.SSLError,
- 'certificate verify failed '):
- self.loop.run_until_complete(f_c)
+ with mock.patch.object(self.loop, 'call_exception_handler'):
+ with test_utils.disable_logger():
+ with self.assertRaisesRegex(ssl.SSLError,
+ 'certificate verify failed '):
+ self.loop.run_until_complete(f_c)
+
+ # execute the loop to log the connection error
+ test_utils.run_briefly(self.loop)
# close connection
self.assertIsNone(proto.transport)
@@ -919,15 +924,20 @@ class EventLoopTestsMixin:
f_c = self.loop.create_unix_connection(MyProto, path,
ssl=sslcontext_client,
server_hostname='invalid')
- with test_utils.disable_logger():
- with self.assertRaisesRegex(ssl.SSLError,
- 'certificate verify failed '):
- self.loop.run_until_complete(f_c)
+ with mock.patch.object(self.loop, 'call_exception_handler'):
+ with test_utils.disable_logger():
+ with self.assertRaisesRegex(ssl.SSLError,
+ 'certificate verify failed '):
+ self.loop.run_until_complete(f_c)
+
+ # execute the loop to log the connection error
+ test_utils.run_briefly(self.loop)
# close connection
self.assertIsNone(proto.transport)
server.close()
+
def test_legacy_create_unix_server_ssl_verify_failed(self):
with test_utils.force_legacy_ssl_support():
self.test_create_unix_server_ssl_verify_failed()
@@ -949,11 +959,12 @@ class EventLoopTestsMixin:
# incorrect server_hostname
f_c = self.loop.create_connection(MyProto, host, port,
ssl=sslcontext_client)
- with test_utils.disable_logger():
- with self.assertRaisesRegex(
- ssl.CertificateError,
- "hostname '127.0.0.1' doesn't match 'localhost'"):
- self.loop.run_until_complete(f_c)
+ with mock.patch.object(self.loop, 'call_exception_handler'):
+ with test_utils.disable_logger():
+ with self.assertRaisesRegex(
+ ssl.CertificateError,
+ "hostname '127.0.0.1' doesn't match 'localhost'"):
+ self.loop.run_until_complete(f_c)
# close connection
proto.transport.close()