diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-01-10 10:23:26 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-10 10:23:26 (GMT) |
commit | 9b07681c09182d4b9d23cd52566a4992b8afecbb (patch) | |
tree | df2742d0c11f6cd8df8c2f973dbb1f8be62b7fca /Lib/asyncio/windows_events.py | |
parent | 6aedfa6b9ac324587f64133c23757a66a8f355bb (diff) | |
download | cpython-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/asyncio/windows_events.py')
-rw-r--r-- | Lib/asyncio/windows_events.py | 28 |
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() |