[Python-checkins] cpython (3.4): asyncio: sync with Tulip

victor.stinner python-checkins at python.org
Thu Jan 29 02:58:13 CET 2015


https://hg.python.org/cpython/rev/65ee4dec4f1d
changeset:   94366:65ee4dec4f1d
branch:      3.4
parent:      94364:44f90017eee3
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Thu Jan 29 02:56:05 2015 +0100
summary:
  asyncio: sync with Tulip

* _SelectorTransport constructor: extra parameter is now optional
* Fix _SelectorDatagramTransport constructor. Only start reading after
  connection_made() has been called.
* 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.

files:
  Lib/asyncio/selector_events.py                |  13 ++++++--
  Lib/test/test_asyncio/test_selector_events.py |  15 +++++++++-
  2 files changed, 24 insertions(+), 4 deletions(-)


diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -467,7 +467,7 @@
 
     _buffer_factory = bytearray  # Constructs initial value for self._buffer.
 
-    def __init__(self, loop, sock, protocol, extra, server=None):
+    def __init__(self, loop, sock, protocol, extra=None, server=None):
         super().__init__(extra, loop)
         self._extra['socket'] = sock
         self._extra['sockname'] = sock.getsockname()
@@ -479,6 +479,7 @@
         self._sock = sock
         self._sock_fd = sock.fileno()
         self._protocol = protocol
+        self._protocol_connected = True
         self._server = server
         self._buffer = self._buffer_factory()
         self._conn_lost = 0  # Set when call to connection_lost scheduled.
@@ -555,7 +556,8 @@
 
     def _call_connection_lost(self, exc):
         try:
-            self._protocol.connection_lost(exc)
+            if self._protocol_connected:
+                self._protocol.connection_lost(exc)
         finally:
             self._sock.close()
             self._sock = None
@@ -718,6 +720,8 @@
         sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs)
 
         super().__init__(loop, sslsock, protocol, extra, server)
+        # the protocol connection is only made after the SSL handshake
+        self._protocol_connected = False
 
         self._server_hostname = server_hostname
         self._waiter = waiter
@@ -797,6 +801,7 @@
         self._read_wants_write = False
         self._write_wants_read = False
         self._loop.add_reader(self._sock_fd, self._read_ready)
+        self._protocol_connected = True
         self._loop.call_soon(self._protocol.connection_made, self)
         # only wake up the waiter when connection_made() has been called
         self._loop.call_soon(self._wakeup_waiter)
@@ -928,8 +933,10 @@
                  waiter=None, extra=None):
         super().__init__(loop, sock, protocol, extra)
         self._address = address
-        self._loop.add_reader(self._sock_fd, self._read_ready)
         self._loop.call_soon(self._protocol.connection_made, self)
+        # only start reading when connection_made() has been called
+        self._loop.call_soon(self._loop.add_reader,
+                             self._sock_fd, self._read_ready)
         if waiter is not None:
             # only wake up the waiter when connection_made() has been called
             self._loop.call_soon(waiter._set_result_unless_cancelled, None)
diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py
--- a/Lib/test/test_asyncio/test_selector_events.py
+++ b/Lib/test/test_asyncio/test_selector_events.py
@@ -1427,7 +1427,7 @@
         self.assertFalse(tr.can_write_eof())
         self.assertRaises(NotImplementedError, tr.write_eof)
 
-    def test_close(self):
+    def check_close(self):
         tr = self._make_one()
         tr.close()
 
@@ -1439,6 +1439,19 @@
         self.assertEqual(tr._conn_lost, 1)
         self.assertEqual(1, self.loop.remove_reader_count[1])
 
+        test_utils.run_briefly(self.loop)
+
+    def test_close(self):
+        self.check_close()
+        self.assertTrue(self.protocol.connection_made.called)
+        self.assertTrue(self.protocol.connection_lost.called)
+
+    def test_close_not_connected(self):
+        self.sslsock.do_handshake.side_effect = ssl.SSLWantReadError
+        self.check_close()
+        self.assertFalse(self.protocol.connection_made.called)
+        self.assertFalse(self.protocol.connection_lost.called)
+
     @unittest.skipIf(ssl is None, 'No SSL support')
     def test_server_hostname(self):
         self.ssl_transport(server_hostname='localhost')

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list