Skip to content

Commit 9b07681

Browse files
authored
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()
1 parent 6aedfa6 commit 9b07681

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

Lib/asyncio/windows_events.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,16 @@ def __init__(self, concurrency=0xffffffff):
408408
self._unregistered = []
409409
self._stopped_serving = weakref.WeakSet()
410410

411+
def _check_closed(self):
412+
if self._iocp is None:
413+
raise RuntimeError('IocpProactor is closed')
414+
411415
def __repr__(self):
412-
return ('<%s overlapped#=%s result#=%s>'
413-
% (self.__class__.__name__, len(self._cache),
414-
len(self._results)))
416+
info = ['overlapped#=%s' % len(self._cache),
417+
'result#=%s' % len(self._results)]
418+
if self._iocp is None:
419+
info.append('closed')
420+
return '<%s %s>' % (self.__class__.__name__, " ".join(info))
415421

416422
def set_loop(self, loop):
417423
self._loop = loop
@@ -618,6 +624,8 @@ def _wait_cancel(self, event, done_callback):
618624
return fut
619625

620626
def _wait_for_handle(self, handle, timeout, _is_cancel):
627+
self._check_closed()
628+
621629
if timeout is None:
622630
ms = _winapi.INFINITE
623631
else:
@@ -660,6 +668,8 @@ def _register_with_iocp(self, obj):
660668
# that succeed immediately.
661669

662670
def _register(self, ov, obj, callback):
671+
self._check_closed()
672+
663673
# Return a future which will be set with the result of the
664674
# operation when it completes. The future's value is actually
665675
# the value returned by callback().
@@ -696,6 +706,7 @@ def _unregister(self, ov):
696706
already be signalled (pending in the proactor event queue). It is also
697707
safe if the event is never signalled (because it was cancelled).
698708
"""
709+
self._check_closed()
699710
self._unregistered.append(ov)
700711

701712
def _get_accept_socket(self, family):
@@ -765,6 +776,10 @@ def _stop_serving(self, obj):
765776
self._stopped_serving.add(obj)
766777

767778
def close(self):
779+
if self._iocp is None:
780+
# already closed
781+
return
782+
768783
# Cancel remaining registered operations.
769784
for address, (fut, ov, obj, callback) in list(self._cache.items()):
770785
if fut.cancelled():
@@ -787,14 +802,15 @@ def close(self):
787802
context['source_traceback'] = fut._source_traceback
788803
self._loop.call_exception_handler(context)
789804

805+
# wait until all cancelled overlapped future complete
790806
while self._cache:
791807
if not self._poll(1):
792808
logger.debug('taking long time to close proactor')
793809

794810
self._results = []
795-
if self._iocp is not None:
796-
_winapi.CloseHandle(self._iocp)
797-
self._iocp = None
811+
812+
_winapi.CloseHandle(self._iocp)
813+
self._iocp = None
798814

799815
def __del__(self):
800816
self.close()

0 commit comments

Comments
 (0)