Index: asyncio/unix_events.py |
=================================================================== |
--- a/asyncio/unix_events.py |
+++ b/asyncio/unix_events.py |
@@ -440,10 +440,13 @@ |
raise NotImplementedError() |
- def set_loop(self, loop): |
- """Reattach the watcher to another event loop. |
+ def attach_loop(self, loop): |
+ """Attach the watcher to an event loop. |
- Note: loop may be None |
+ If the watcher was previously attached to an event loop, then it is |
+ first detached before attaching to the new loop. |
+ |
+ Note: loop may be None. |
""" |
raise NotImplementedError() |
@@ -467,15 +470,11 @@ |
class BaseChildWatcher(AbstractChildWatcher): |
- def __init__(self, loop): |
+ def __init__(self): |
self._loop = None |
- self._callbacks = {} |
- |
- self.set_loop(loop) |
def close(self): |
- self.set_loop(None) |
- self._callbacks.clear() |
+ self.attach_loop(None) |
def _do_waitpid(self, expected_pid): |
raise NotImplementedError() |
@@ -483,7 +482,7 @@ |
def _do_waitpid_all(self): |
raise NotImplementedError() |
- def set_loop(self, loop): |
+ def attach_loop(self, loop): |
assert loop is None or isinstance(loop, events.AbstractEventLoop) |
if self._loop is not None: |
@@ -497,13 +496,6 @@ |
# during the switch. |
self._do_waitpid_all() |
- def remove_child_handler(self, pid): |
- try: |
- del self._callbacks[pid] |
- return True |
- except KeyError: |
- return False |
- |
def _sig_chld(self): |
try: |
self._do_waitpid_all() |
@@ -535,6 +527,14 @@ |
big number of children (O(n) each time SIGCHLD is raised) |
""" |
+ def __init__(self): |
+ super().__init__() |
+ self._callbacks = {} |
+ |
+ def close(self): |
+ self._callbacks.clear() |
+ super().close() |
+ |
def __enter__(self): |
return self |
@@ -547,6 +547,13 @@ |
# Prevent a race condition in case the child is already terminated. |
self._do_waitpid(pid) |
+ def remove_child_handler(self, pid): |
+ try: |
+ del self._callbacks[pid] |
+ return True |
+ except KeyError: |
+ return False |
+ |
def _do_waitpid_all(self): |
for pid in list(self._callbacks): |
@@ -592,16 +599,17 @@ |
There is no noticeable overhead when handling a big number of children |
(O(1) each time a child terminates). |
""" |
- def __init__(self, loop): |
- super().__init__(loop) |
- |
+ def __init__(self): |
+ super().__init__() |
+ self._callbacks = {} |
self._lock = threading.Lock() |
self._zombies = {} |
self._forks = 0 |
def close(self): |
+ self._callbacks.clear() |
+ self._zombies.clear() |
super().close() |
- self._zombies.clear() |
def __enter__(self): |
with self._lock: |
@@ -642,6 +650,13 @@ |
else: |
callback(pid, returncode, *args) |
+ def remove_child_handler(self, pid): |
+ try: |
+ del self._callbacks[pid] |
+ return True |
+ except KeyError: |
+ return False |
+ |
def _do_waitpid_all(self): |
# Because of signal coalescing, we must keep calling waitpid() as |
# long as we're able to reap a child. |
@@ -686,25 +701,24 @@ |
def _init_watcher(self): |
with events._lock: |
if self._watcher is None: # pragma: no branch |
+ self._watcher = SafeChildWatcher() |
if isinstance(threading.current_thread(), |
threading._MainThread): |
- self._watcher = SafeChildWatcher(self._local._loop) |
- else: |
- self._watcher = SafeChildWatcher(None) |
+ self._watcher.attach_loop(self._local._loop) |
def set_event_loop(self, loop): |
"""Set the event loop. |
As a side effect, if a child watcher was set before, then calling |
- .set_event_loop() from the main thread will call .set_loop(loop) on the |
- child watcher. |
+ .set_event_loop() from the main thread will call .attach_loop(loop) on |
+ the child watcher. |
""" |
super().set_event_loop(loop) |
if self._watcher is not None and \ |
isinstance(threading.current_thread(), threading._MainThread): |
- self._watcher.set_loop(loop) |
+ self._watcher.attach_loop(loop) |
def get_child_watcher(self): |
"""Get the child watcher |