8000 Fix _SelectorSslTransport.close() · python/asyncio@7a46eda · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Nov 23, 2017. It is now read-only.

Commit 7a46eda

Browse files
committed
Fix _SelectorSslTransport.close()
Don't call protocol.connection_lost() if protocol.connection_made() was not called yet: if the SSL handshake failed or is still in progress. The close() method can be called if the creation of the connection is cancelled, by a timeout for example.
1 parent 1162bf2 commit 7a46eda

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

asyncio/selector_events.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ def __init__(self, loop, sock, protocol, extra=None, server=None):
479479
self._sock = sock
480480
self._sock_fd = sock.fileno()
481481
self._protocol = protocol
482+
self._protocol_connected = True
482483
self._server = server
483484
self._buffer = self._buffer_factory()
484485
self._conn_lost = 0 # Set when call to connection_lost scheduled.
@@ -555,7 +556,8 @@ def _force_close(self, exc):
555556

556557
def _call_connection_lost(self, exc):
557558
try:
558-
self._protocol.connection_lost(exc)
559+
if self._protocol_connected:
560+
self._protocol.connection_lost(exc)
559561
finally:
560562
self._sock.close()
561563
self._sock = None
@@ -718,6 +720,8 @@ def __init__(self, loop, rawsock, protocol, sslcontext, waiter=None,
718720
sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs)
719721

720722
super().__init__(loop, sslsock, protocol, extra, server)
723+
# the protocol connection is only made after the SSL handshake
724+
self._protocol_connected = False
721725

722726
self._server_hostname = server_hostname
723727
self._waiter = waiter
@@ -797,6 +801,7 @@ def _on_handshake(self, start_time):
797801
self._read_wants_write = False
798802
self._write_wants_read = False
799803
self._loop.add_reader(self._sock_fd, self._read_ready)
804+
self._protocol_connected = True
800805
self._loop.call_soon(self._protocol.connection_made, self)
801806
# only wake up the waiter when connection_made() has been called
802807
self._loop.call_soon(self._wakeup_waiter)

tests/test_selector_events.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,7 @@ def test_write_eof(self):
14271427
self.assertFalse(tr.can_write_eof())
14281428
self.assertRaises(NotImplementedError, tr.write_eof)
14291429

1430-
def test_close(self):
1430+
def check_close(self):
14311431
tr = self._make_one()
14321432
tr.close()
14331433

@@ -1439,6 +1439,19 @@ def test_close(self):
14391439
self.assertEqual(tr._conn_lost, 1)
14401440
self.assertEqual(1, self.loop.remove_reader_count[1])
14411441

1442+
test_utils.run_briefly(self.loop)
1443+
1444+
def test_close(self):
1445+
self.check_close()
1446+
self.assertTrue(self.protocol.connection_made.called)
1447+
self.assertTrue(self.protocol.connection_lost.called)
1448+
1449+
def test_close_not_connected(self):
1450+
self.sslsock.do_handshake.s 6B55 ide_effect = ssl.SSLWantReadError
1451+
self.check_close()
1452+
self.assertFalse(self.protocol.connection_made.called)
1453+
self.assertFalse(self.protocol.connection_lost.called)
1454+
14421455
@unittest.skipIf(ssl is None, 'No SSL support')
14431456
def test_server_hostname(self):
14441457
self.ssl_transport(server_hostname='localhost')

0 commit comments

Comments
 (0)
0