Commit ae835d00 authored by Victor Stinner's avatar Victor Stinner

Issue #23095, asyncio: Fix _WaitHandleFuture.cancel()

If UnregisterWaitEx() fais with ERROR_IO_PENDING, it doesn't mean that the wait
is unregistered yet. We still have to wait until the wait is cancelled.
parent 9b9efe3d
...@@ -126,14 +126,12 @@ class _BaseWaitHandleFuture(futures.Future): ...@@ -126,14 +126,12 @@ class _BaseWaitHandleFuture(futures.Future):
return return
self._registered = False self._registered = False
wait_handle = self._wait_handle
self._wait_handle = None
try: try:
_overlapped.UnregisterWait(self._wait_handle) _overlapped.UnregisterWait(wait_handle)
except OSError as exc: except OSError as exc:
self._wait_handle = None if exc.winerror != _overlapped.ERROR_IO_PENDING:
if exc.winerror == _overlapped.ERROR_IO_PENDING:
# ERROR_IO_PENDING is not an error, the wait was unregistered
self._unregister_wait_cb(None)
elif exc.winerror != _overlapped.ERROR_IO_PENDING:
context = { context = {
'message': 'Failed to unregister the wait handle', 'message': 'Failed to unregister the wait handle',
'exception': exc, 'exception': exc,
...@@ -142,9 +140,10 @@ class _BaseWaitHandleFuture(futures.Future): ...@@ -142,9 +140,10 @@ class _BaseWaitHandleFuture(futures.Future):
if self._source_traceback: if self._source_traceback:
context['source_traceback'] = self._source_traceback context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context) self._loop.call_exception_handler(context)
else: return
self._wait_handle = None # ERROR_IO_PENDING means that the unregister is pending
self._unregister_wait_cb(None)
self._unregister_wait_cb(None)
def cancel(self): def cancel(self):
self._unregister_wait() self._unregister_wait()
...@@ -209,14 +208,12 @@ class _WaitHandleFuture(_BaseWaitHandleFuture): ...@@ -209,14 +208,12 @@ class _WaitHandleFuture(_BaseWaitHandleFuture):
return return
self._registered = False self._registered = False
wait_handle = self._wait_handle
self._wait_handle = None
try: try:
_overlapped.UnregisterWaitEx(self._wait_handle, self._event) _overlapped.UnregisterWaitEx(wait_handle, self._event)
except OSError as exc: except OSError as exc:
self._wait_handle = None if exc.winerror != _overlapped.ERROR_IO_PENDING:
if exc.winerror == _overlapped.ERROR_IO_PENDING:
# ERROR_IO_PENDING is not an error, the wait was unregistered
self._unregister_wait_cb(None)
elif exc.winerror != _overlapped.ERROR_IO_PENDING:
context = { context = {
'message': 'Failed to unregister the wait handle', 'message': 'Failed to unregister the wait handle',
'exception': exc, 'exception': exc,
...@@ -225,11 +222,11 @@ class _WaitHandleFuture(_BaseWaitHandleFuture): ...@@ -225,11 +222,11 @@ class _WaitHandleFuture(_BaseWaitHandleFuture):
if self._source_traceback: if self._source_traceback:
context['source_traceback'] = self._source_traceback context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context) self._loop.call_exception_handler(context)
else: return
self._wait_handle = None # ERROR_IO_PENDING is not an error, the wait was unregistered
self._event_fut = self._proactor._wait_cancel(
self._event, self._event_fut = self._proactor._wait_cancel(self._event,
self._unregister_wait_cb) self._unregister_wait_cb)
class PipeServer(object): class PipeServer(object):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment