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