Closing transport during handshake process leaks socket (#480)
authorNikolay Kim <fafhrd91@gmail.com>
Fri, 9 Jun 2017 21:46:14 +0000 (14:46 -0700)
committerYury Selivanov <yury@magic.io>
Fri, 9 Jun 2017 21:46:14 +0000 (17:46 -0400)
Lib/asyncio/sslproto.py
Lib/test/test_asyncio/test_sslproto.py
Misc/NEWS

index 61d31a3b295ee47a0a239030fcf8ef26b4974ca6..a7f1e61596d6a55673b933ba96c974b69eed7f8c 100644 (file)
@@ -546,8 +546,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))
index f1771c5561afea819c3fdc6590efbc1d1d84d3fb..bcd236ea2632ed728a91a4b485b68ed7c5535f14 100644 (file)
@@ -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)
index c01363955dc1864d5e770be82ad11859cb0c968e..1bc38b7bd2ca7678be7ac6b2bf11ade14cb87f5c 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -350,6 +350,9 @@ Extension Modules
 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.