From 0b807a849564f5fefec5630b4a478789a9de1d22 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 20 Sep 2017 14:05:11 -0700 Subject: [PATCH] Handle session close during connection, KeyError: #2193 --- aiohttp/connector.py | 11 ++++++++--- changes/2193.bugfix | 1 + tests/test_connector.py | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 changes/2193.bugfix diff --git a/aiohttp/connector.py b/aiohttp/connector.py index dc45fc88c0c..b0fe3f43f20 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -10,7 +10,8 @@ from types import MappingProxyType from . import hdrs, helpers -from .client_exceptions import (ClientConnectorError, ClientHttpProxyError, +from .client_exceptions import (ClientConnectionError, ClientConnectorError, + ClientHttpProxyError, ClientProxyConnectionError, ServerFingerprintMismatch) from .client_proto import ResponseHandler @@ -386,11 +387,15 @@ def connect(self, req): self._acquired_per_host[key].add(placeholder) try: proto = yield from self._create_connection(req) + if self._closed: + proto.close() + raise ClientConnectionError("Connector is closed.") except OSError as exc: raise ClientConnectorError(key, exc) from exc finally: - self._acquired.remove(placeholder) - self._acquired_per_host[key].remove(placeholder) + if not self._closed: + self._acquired.remove(placeholder) + self._acquired_per_host[key].remove(placeholder) self._acquired.add(proto) self._acquired_per_host[key].add(proto) diff --git a/changes/2193.bugfix b/changes/2193.bugfix new file mode 100644 index 00000000000..883b81ce982 --- /dev/null +++ b/changes/2193.bugfix @@ -0,0 +1 @@ +Handle session close during connection, KeyError: diff --git a/tests/test_connector.py b/tests/test_connector.py index 680d8730b0c..18b1d07c7f1 100644 --- a/tests/test_connector.py +++ b/tests/test_connector.py @@ -588,6 +588,29 @@ def test_connect_connection_error(loop): assert ctx.value.ssl == req.ssl +@asyncio.coroutine +def test_close_during_connect(loop): + proto = mock.Mock() + proto.is_connected.return_value = True + + fut = helpers.create_future(loop) + req = ClientRequest('GET', URL('http://host:80'), loop=loop) + + conn = aiohttp.BaseConnector(loop=loop) + conn._create_connection = mock.Mock() + conn._create_connection.return_value = fut + + task = helpers.ensure_future(conn.connect(req), loop=loop) + yield from asyncio.sleep(0, loop=loop) + conn.close() + + fut.set_result(proto) + with pytest.raises(aiohttp.ClientConnectionError): + yield from task + + assert proto.close.called + + def test_ctor_cleanup(): loop = mock.Mock() loop.time.return_value = 1.5