@@ -440,10 +440,13 @@ def remove_child_handler(self, pid):
440440
441441 raise NotImplementedError ()
442442
443- def set_loop (self , loop ):
444- """Reattach the watcher to another event loop.
443+ def attach_loop (self , loop ):
444+ """Attach the watcher to an event loop.
445445
446- Note: loop may be None
446+ If the watcher was previously attached to an event loop, then it is
447+ first detached before attaching to the new loop.
448+
449+ Note: loop may be None.
447450 """
448451 raise NotImplementedError ()
449452
@@ -467,23 +470,19 @@ def __exit__(self, a, b, c):
467470
468471class BaseChildWatcher (AbstractChildWatcher ):
469472
470- def __init__ (self , loop ):
473+ def __init__ (self ):
471474 self ._loop = None
472- self ._callbacks = {}
473-
474- self .set_loop (loop )
475475
476476 def close (self ):
477- self .set_loop (None )
478- self ._callbacks .clear ()
477+ self .attach_loop (None )
479478
480479 def _do_waitpid (self , expected_pid ):
481480 raise NotImplementedError ()
482481
483482 def _do_waitpid_all (self ):
484483 raise NotImplementedError ()
485484
486- def set_loop (self , loop ):
485+ def attach_loop (self , loop ):
487486 assert loop is None or isinstance (loop , events .AbstractEventLoop )
488487
489488 if self ._loop is not None :
@@ -497,13 +496,6 @@ def set_loop(self, loop):
497496 # during the switch.
498497 self ._do_waitpid_all ()
499498
500- def remove_child_handler (self , pid ):
501- try :
502- del self ._callbacks [pid ]
503- return True
504- except KeyError :
505- return False
506-
507499 def _sig_chld (self ):
508500 try :
509501 self ._do_waitpid_all ()
@@ -535,6 +527,14 @@ class SafeChildWatcher(BaseChildWatcher):
535527 big number of children (O(n) each time SIGCHLD is raised)
536528 """
537529
530+ def __init__ (self ):
531+ super ().__init__ ()
532+ self ._callbacks = {}
533+
534+ def close (self ):
535+ self ._callbacks .clear ()
536+ super ().close ()
537+
538538 def __enter__ (self ):
539539 return self
540540
@@ -547,6 +547,13 @@ def add_child_handler(self, pid, callback, *args):
547547 # Prevent a race condition in case the child is already terminated.
548548 self ._do_waitpid (pid )
549549
550+ def remove_child_handler (self , pid ):
551+ try :
552+ del self ._callbacks [pid ]
553+ return True
554+ except KeyError :
555+ return False
556+
550557 def _do_waitpid_all (self ):
551558
552559 for pid in list (self ._callbacks ):
@@ -592,17 +599,17 @@ class FastChildWatcher(BaseChildWatcher):
592599 There is no noticeable overhead when handling a big number of children
593600 (O(1) each time a child terminates).
594601 """
595- def __init__ (self , loop ):
602+ def __init__ (self ):
603+ super ().__init__ ()
604+ self ._callbacks = {}
596605 self ._lock = threading .Lock ()
597606 self ._zombies = {}
598607 self ._forks = 0
599- # Call base class constructor last because it calls back into
600- # the subclass (set_loop() calls _do_waitpid()).
601- super ().__init__ (loop )
602608
603609 def close (self ):
604- super (). close ()
610+ self . _callbacks . clear ()
605611 self ._zombies .clear ()
612+ super ().close ()
606613
607614 def __enter__ (self ):
608615 with self ._lock :
@@ -643,6 +650,13 @@ def add_child_handler(self, pid, callback, *args):
643650 else :
644651 callback (pid , returncode , * args )
645652
653+ def remove_child_handler (self , pid ):
654+ try :
655+ del self ._callbacks [pid ]
656+ return True
657+ except KeyError :
658+ return False
659+
646660 def _do_waitpid_all (self ):
647661 # Because of signal coalescing, we must keep calling waitpid() as
648662 # long as we're able to reap a child.
@@ -687,25 +701,24 @@ def __init__(self):
687701 def _init_watcher (self ):
688702 with events ._lock :
689703 if self ._watcher is None : # pragma: no branch
704+ self ._watcher = SafeChildWatcher ()
690705 if isinstance (threading .current_thread (),
691706 threading ._MainThread ):
692- self ._watcher = SafeChildWatcher (self ._local ._loop )
693- else :
694- self ._watcher = SafeChildWatcher (None )
707+ self ._watcher .attach_loop (self ._local ._loop )
695708
696709 def set_event_loop (self , loop ):
697710 """Set the event loop.
698711
699712 As a side effect, if a child watcher was set before, then calling
700- .set_event_loop() from the main thread will call .set_loop (loop) on the
701- child watcher.
713+ .set_event_loop() from the main thread will call .attach_loop (loop) on
714+ the child watcher.
702715 """
703716
704717 super ().set_event_loop (loop )
705718
706719 if self ._watcher is not None and \
707720 isinstance (threading .current_thread (), threading ._MainThread ):
708- self ._watcher .set_loop (loop )
721+ self ._watcher .attach_loop (loop )
709722
710723 def get_child_watcher (self ):
711724 """Get the child watcher
0 commit comments