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.
This commit is contained in:
Victor Stinner 2015-01-26 22:30:28 +01:00
parent e0fd157ba0
commit 24dfa3c1d6
1 changed files with 17 additions and 20 deletions

View File

@ -126,14 +126,12 @@ class _BaseWaitHandleFuture(futures.Future):
return
self._registered = False
try:
_overlapped.UnregisterWait(self._wait_handle)
except OSError as exc:
wait_handle = self._wait_handle
self._wait_handle = None
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:
try:
_overlapped.UnregisterWait(wait_handle)
except OSError as exc:
if exc.winerror != _overlapped.ERROR_IO_PENDING:
context = {
'message': 'Failed to unregister the wait handle',
'exception': exc,
@ -142,8 +140,9 @@ class _BaseWaitHandleFuture(futures.Future):
if self._source_traceback:
context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context)
else:
self._wait_handle = None
return
# ERROR_IO_PENDING means that the unregister is pending
self._unregister_wait_cb(None)
def cancel(self):
@ -209,14 +208,12 @@ class _WaitHandleFuture(_BaseWaitHandleFuture):
return
self._registered = False
try:
_overlapped.UnregisterWaitEx(self._wait_handle, self._event)
except OSError as exc:
wait_handle = self._wait_handle
self._wait_handle = None
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:
try:
_overlapped.UnregisterWaitEx(wait_handle, self._event)
except OSError as exc:
if exc.winerror != _overlapped.ERROR_IO_PENDING:
context = {
'message': 'Failed to unregister the wait handle',
'exception': exc,
@ -225,10 +222,10 @@ class _WaitHandleFuture(_BaseWaitHandleFuture):
if self._source_traceback:
context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context)
else:
self._wait_handle = None
self._event_fut = self._proactor._wait_cancel(
self._event,
return
# ERROR_IO_PENDING is not an error, the wait was unregistered
self._event_fut = self._proactor._wait_cancel(self._event,
self._unregister_wait_cb)