[Python-checkins] cpython (3.4): asyncio, Tulip issue 204: Fix IocpProactor.accept_pipe()

victor.stinner python-checkins at python.org
Thu Jan 22 23:52:00 CET 2015


https://hg.python.org/cpython/rev/6f0b03c17b50
changeset:   94245:6f0b03c17b50
branch:      3.4
parent:      94243:76e3f80eb680
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Thu Jan 22 23:50:03 2015 +0100
summary:
  asyncio, Tulip issue 204: Fix IocpProactor.accept_pipe()

Overlapped.ConnectNamedPipe() now returns a boolean: True if the pipe is
connected (if ConnectNamedPipe() failed with ERROR_PIPE_CONNECTED), False if
the connection is in progress.

This change removes multiple hacks in IocpProactor.

files:
  Lib/asyncio/windows_events.py |  41 +++++++++-------------
  Modules/overlapped.c          |   4 +-
  2 files changed, 19 insertions(+), 26 deletions(-)


diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py
--- a/Lib/asyncio/windows_events.py
+++ b/Lib/asyncio/windows_events.py
@@ -490,16 +490,21 @@
     def accept_pipe(self, pipe):
         self._register_with_iocp(pipe)
         ov = _overlapped.Overlapped(NULL)
-        ov.ConnectNamedPipe(pipe.fileno())
+        connected = ov.ConnectNamedPipe(pipe.fileno())
+
+        if connected:
+            # ConnectNamePipe() failed with ERROR_PIPE_CONNECTED which means
+            # that the pipe is connected. There is no need to wait for the
+            # completion of the connection.
+            f = futures.Future(loop=self._loop)
+            f.set_result(pipe)
+            return f
 
         def finish_accept_pipe(trans, key, ov):
             ov.getresult()
             return pipe
 
-        # FIXME: Tulip issue 196: why do we need register=False?
-        # See also the comment in the _register() method
-        return self._register(ov, pipe, finish_accept_pipe,
-                              register=False)
+        return self._register(ov, pipe, finish_accept_pipe)
 
     def _connect_pipe(self, fut, address, delay):
         # Unfortunately there is no way to do an overlapped connect to a pipe.
@@ -581,15 +586,14 @@
             # to avoid sending notifications to completion port of ops
             # that succeed immediately.
 
-    def _register(self, ov, obj, callback,
-                  wait_for_post=False, register=True):
+    def _register(self, ov, obj, callback):
         # Return a future which will be set with the result of the
         # operation when it completes.  The future's value is actually
         # the value returned by callback().
         f = _OverlappedFuture(ov, loop=self._loop)
         if f._source_traceback:
             del f._source_traceback[-1]
-        if not ov.pending and not wait_for_post:
+        if not ov.pending:
             # The operation has completed, so no need to postpone the
             # work.  We cannot take this short cut if we need the
             # NumberOfBytes, CompletionKey values returned by
@@ -605,18 +609,11 @@
             # Register the overlapped operation to keep a reference to the
             # OVERLAPPED object, otherwise the memory is freed and Windows may
             # read uninitialized memory.
-            #
-            # For an unknown reason, ConnectNamedPipe() behaves differently:
-            # the completion is not notified by GetOverlappedResult() if we
-            # already called GetOverlappedResult(). For this specific case, we
-            # don't expect notification (register is set to False).
-        else:
-            register = True
-        if register:
-            # Register the overlapped operation for later.  Note that
-            # we only store obj to prevent it from being garbage
-            # collected too early.
-            self._cache[ov.address] = (f, ov, obj, callback)
+
+        # Register the overlapped operation for later.  Note that
+        # we only store obj to prevent it from being garbage
+        # collected too early.
+        self._cache[ov.address] = (f, ov, obj, callback)
         return f
 
     def _unregister(self, ov):
@@ -708,10 +705,6 @@
             elif isinstance(fut, _WaitCancelFuture):
                 # _WaitCancelFuture must not be cancelled
                 pass
-            elif fut.done():
-                # FIXME: Tulip issue 196: remove this case, it should not
-                # happen
-                del self._cache[address]
             else:
                 try:
                     fut.cancel()
diff --git a/Modules/overlapped.c b/Modules/overlapped.c
--- a/Modules/overlapped.c
+++ b/Modules/overlapped.c
@@ -1117,10 +1117,10 @@
     switch (err) {
         case ERROR_PIPE_CONNECTED:
             mark_as_completed(&self->overlapped);
-            Py_RETURN_NONE;
+            Py_RETURN_TRUE;
         case ERROR_SUCCESS:
         case ERROR_IO_PENDING:
-            Py_RETURN_NONE;
+            Py_RETURN_FALSE;
         default:
             self->type = TYPE_NOT_STARTED;
             return SetFromWindowsErr(err);

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


More information about the Python-checkins mailing list