From 7a16a4535d691eff79fcc65ae57e69741e6c83df Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Fri, 9 Jun 2017 18:33:31 -0400 Subject: [PATCH] Closing transport during handshake process leaks socket (#480) (#2044) --- Lib/asyncio/sslproto.py | 7 +++++-- Lib/test/test_asyncio/test_sslproto.py | 15 +++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index ab7ff0bf93..6e9ce2968a 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -551,8 +551,11 @@ class SSLProtocol(protocols.Protocol): def _start_shutdown(self): if self._in_shutdown: return - self._in_shutdown = True - self._write_appdata(b'') + if self._in_handshake: + self._abort() + else: + self._in_shutdown = True + self._write_appdata(b'') def _write_appdata(self, data): self._write_backlog.append((data, 0)) diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index f1771c5561..bcd236ea26 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -42,6 +42,7 @@ class SslProtoHandshakeTests(test_utils.TestCase): sslpipe.do_handshake.side_effect = mock_handshake with mock.patch('asyncio.sslproto._SSLPipe', return_value=sslpipe): ssl_proto.connection_made(transport) + return transport def test_cancel_handshake(self): # Python issue #23197: cancelling a handshake must not raise an @@ -95,6 +96,20 @@ class SslProtoHandshakeTests(test_utils.TestCase): test_utils.run_briefly(self.loop) self.assertIsInstance(waiter.exception(), ConnectionAbortedError) + def test_close_during_handshake(self): + # bpo-29743 Closing transport during handshake process leaks socket + waiter = asyncio.Future(loop=self.loop) + ssl_proto = self.ssl_protocol(waiter) + + def do_handshake(callback): + return [] + + transport = self.connection_made(ssl_proto) + test_utils.run_briefly(self.loop) + + ssl_proto._app_transport.close() + self.assertTrue(transport.abort.called) + def test_get_extra_info_on_closed_connection(self): waiter = asyncio.Future(loop=self.loop) ssl_proto = self.ssl_protocol(waiter) diff --git a/Misc/NEWS b/Misc/NEWS index 0342c71cd6..7bd46d5578 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,9 @@ Core and Builtins Library ------- +- bpo-29743: Closing transport during handshake process leaks open socket. + Patch by Nikolay Kim + - bpo-27585: Fix waiter cancellation in asyncio.Lock. Patch by Mathieu Sornay. -- 2.50.0