Unverified Kaydet (Commit) 9b07681c authored tarafından Victor Stinner's avatar Victor Stinner Kaydeden (comit) GitHub

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()
üst 6aedfa6b
...@@ -408,10 +408,16 @@ class IocpProactor: ...@@ -408,10 +408,16 @@ class IocpProactor:
self._unregistered = [] self._unregistered = []
self._stopped_serving = weakref.WeakSet() self._stopped_serving = weakref.WeakSet()
def _check_closed(self):
if self._iocp is None:
raise RuntimeError('IocpProactor is closed')
def __repr__(self): def __repr__(self):
return ('<%s overlapped#=%s result#=%s>' info = ['overlapped#=%s' % len(self._cache),
% (self.__class__.__name__, len(self._cache), 'result#=%s' % len(self._results)]
len(self._results))) if self._iocp is None:
info.append('closed')
return '<%s %s>' % (self.__class__.__name__, " ".join(info))
def set_loop(self, loop): def set_loop(self, loop):
self._loop = loop self._loop = loop
...@@ -618,6 +624,8 @@ class IocpProactor: ...@@ -618,6 +624,8 @@ class IocpProactor:
return fut return fut
def _wait_for_handle(self, handle, timeout, _is_cancel): def _wait_for_handle(self, handle, timeout, _is_cancel):
self._check_closed()
if timeout is None: if timeout is None:
ms = _winapi.INFINITE ms = _winapi.INFINITE
else: else:
...@@ -660,6 +668,8 @@ class IocpProactor: ...@@ -660,6 +668,8 @@ class IocpProactor:
# that succeed immediately. # that succeed immediately.
def _register(self, ov, obj, callback): def _register(self, ov, obj, callback):
self._check_closed()
# 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().
...@@ -696,6 +706,7 @@ class IocpProactor: ...@@ -696,6 +706,7 @@ class IocpProactor:
already be signalled (pending in the proactor event queue). It is also already be signalled (pending in the proactor event queue). It is also
safe if the event is never signalled (because it was cancelled). safe if the event is never signalled (because it was cancelled).
""" """
self._check_closed()
self._unregistered.append(ov) self._unregistered.append(ov)
def _get_accept_socket(self, family): def _get_accept_socket(self, family):
...@@ -765,6 +776,10 @@ class IocpProactor: ...@@ -765,6 +776,10 @@ class IocpProactor:
self._stopped_serving.add(obj) self._stopped_serving.add(obj)
def close(self): def close(self):
if self._iocp is None:
# already closed
return
# Cancel remaining registered operations. # Cancel remaining registered operations.
for address, (fut, ov, obj, callback) in list(self._cache.items()): for address, (fut, ov, obj, callback) in list(self._cache.items()):
if fut.cancelled(): if fut.cancelled():
...@@ -787,12 +802,13 @@ class IocpProactor: ...@@ -787,12 +802,13 @@ class IocpProactor:
context['source_traceback'] = fut._source_traceback context['source_traceback'] = fut._source_traceback
self._loop.call_exception_handler(context) self._loop.call_exception_handler(context)
# wait until all cancelled overlapped future complete
while self._cache: while self._cache:
if not self._poll(1): if not self._poll(1):
logger.debug('taking long time to close proactor') logger.debug('taking long time to close proactor')
self._results = [] self._results = []
if self._iocp is not None:
_winapi.CloseHandle(self._iocp) _winapi.CloseHandle(self._iocp)
self._iocp = None self._iocp = None
......
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