MCPcopy Index your code
hub / github.com/python/cpython / _ThreadedChildWatcher

Class _ThreadedChildWatcher

Lib/asyncio/unix_events.py:893–951  ·  view source on GitHub ↗

Threaded child watcher implementation. The watcher uses a thread per process for waiting for the process finish. It doesn't require subscription on POSIX signal but a thread creation is not free. The watcher has O(1) complexity, its performance doesn't depend on amount of

Source from the content-addressed store, hash-verified

891 callback(pid, returncode, *args)
892
893class _ThreadedChildWatcher:
894 """Threaded child watcher implementation.
895
896 The watcher uses a thread per process
897 for waiting for the process finish.
898
899 It doesn't require subscription on POSIX signal
900 but a thread creation is not free.
901
902 The watcher has O(1) complexity, its performance doesn't depend
903 on amount of spawn processes.
904 """
905
906 def __init__(self):
907 self._pid_counter = itertools.count(0)
908 self._threads = {}
909
910 def __del__(self, _warn=warnings.warn):
911 threads = [thread for thread in list(self._threads.values())
912 if thread.is_alive()]
913 if threads:
914 _warn(f"{self.__class__} has registered but not finished child processes",
915 ResourceWarning,
916 source=self)
917
918 def add_child_handler(self, pid, callback, *args):
919 loop = events.get_running_loop()
920 thread = threading.Thread(target=self._do_waitpid,
921 name=f"asyncio-waitpid-{next(self._pid_counter)}",
922 args=(loop, pid, callback, args),
923 daemon=True)
924 self._threads[pid] = thread
925 thread.start()
926
927 def _do_waitpid(self, loop, expected_pid, callback, args):
928 assert expected_pid > 0
929
930 try:
931 pid, status = os.waitpid(expected_pid, 0)
932 except ChildProcessError:
933 # The child process is already reaped
934 # (may happen if waitpid() is called elsewhere).
935 pid = expected_pid
936 returncode = 255
937 logger.warning(
938 "Unknown child process pid %d, will report returncode 255",
939 pid)
940 else:
941 returncode = waitstatus_to_exitcode(status)
942 if loop.get_debug():
943 logger.debug('process %s exited with returncode %s',
944 expected_pid, returncode)
945
946 if loop.is_closed():
947 logger.warning("Loop %r that handles pid %r is closed", loop, pid)
948 else:
949 loop.call_soon_threadsafe(callback, pid, returncode, *args)
950

Callers 1

__init__Method · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…