summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-01-10 10:23:26 (GMT)
committerGitHub <noreply@github.com>2019-01-10 10:23:26 (GMT)
commit9b07681c09182d4b9d23cd52566a4992b8afecbb (patch)
treedf2742d0c11f6cd8df8c2f973dbb1f8be62b7fca /Lib
parent6aedfa6b9ac324587f64133c23757a66a8f355bb (diff)
downloadcpython-9b07681c09182d4b9d23cd52566a4992b8afecbb.zip
cpython-9b07681c09182d4b9d23cd52566a4992b8afecbb.tar.gz
cpython-9b07681c09182d4b9d23cd52566a4992b8afecbb.tar.bz2
IocpProactor: prevent modification if closed (GH-11494)
* _wait_for_handle(), _register() and _unregister() methods of IocpProactor now raise an exception if closed * Add "closed" to IocpProactor.__repr__() * Simplify IocpProactor.close()
Diffstat (limited to 'Lib')
-rw-r--r--Lib/asyncio/windows_events.py28
1 files changed, 22 insertions, 6 deletions
diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py
index 0f3e9f4..bdb9a6e 100644
--- a/Lib/asyncio/windows_events.py
+++ b/Lib/asyncio/windows_events.py
@@ -408,10 +408,16 @@ class IocpProactor:
self._unregistered = []
self._stopped_serving = weakref.WeakSet()
+ def _check_closed(self):
+ if self._iocp is None:
+ raise RuntimeError('IocpProactor is closed')
+
def __repr__(self):
- return ('<%s overlapped#=%s result#=%s>'
- % (self.__class__.__name__, len(self._cache),
- len(self._results)))
+ info = ['overlapped#=%s' % len(self._cache),
+ 'result#=%s' % len(self._results)]
+ if self._iocp is None:
+ info.append('closed')
+ return '<%s %s>' % (self.__class__.__name__, " ".join(info))
def set_loop(self, loop):
self._loop = loop
@@ -618,6 +624,8 @@ class IocpProactor:
return fut
def _wait_for_handle(self, handle, timeout, _is_cancel):
+ self._check_closed()
+
if timeout is None:
ms = _winapi.INFINITE
else:
@@ -660,6 +668,8 @@ class IocpProactor:
# that succeed immediately.
def _register(self, ov, obj, callback):
+ self._check_closed()
+
# 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().
@@ -696,6 +706,7 @@ class IocpProactor:
already be signalled (pending in the proactor event queue). It is also
safe if the event is never signalled (because it was cancelled).
"""
+ self._check_closed()
self._unregistered.append(ov)
def _get_accept_socket(self, family):
@@ -765,6 +776,10 @@ class IocpProactor:
self._stopped_serving.add(obj)
def close(self):
+ if self._iocp is None:
+ # already closed
+ return
+
# Cancel remaining registered operations.
for address, (fut, ov, obj, callback) in list(self._cache.items()):
if fut.cancelled():
@@ -787,14 +802,15 @@ class IocpProactor:
context['source_traceback'] = fut._source_traceback
self._loop.call_exception_handler(context)
+ # wait until all cancelled overlapped future complete
while self._cache:
if not self._poll(1):
logger.debug('taking long time to close proactor')
self._results = []
- if self._iocp is not None:
- _winapi.CloseHandle(self._iocp)
- self._iocp = None
+
+ _winapi.CloseHandle(self._iocp)
+ self._iocp = None
def __del__(self):
self.close()