17db96d56Sopenharmony_ci# 27db96d56Sopenharmony_ci# Module providing the `Process` class which emulates `threading.Thread` 37db96d56Sopenharmony_ci# 47db96d56Sopenharmony_ci# multiprocessing/process.py 57db96d56Sopenharmony_ci# 67db96d56Sopenharmony_ci# Copyright (c) 2006-2008, R Oudkerk 77db96d56Sopenharmony_ci# Licensed to PSF under a Contributor Agreement. 87db96d56Sopenharmony_ci# 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci__all__ = ['BaseProcess', 'current_process', 'active_children', 117db96d56Sopenharmony_ci 'parent_process'] 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci# 147db96d56Sopenharmony_ci# Imports 157db96d56Sopenharmony_ci# 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ciimport os 187db96d56Sopenharmony_ciimport sys 197db96d56Sopenharmony_ciimport signal 207db96d56Sopenharmony_ciimport itertools 217db96d56Sopenharmony_ciimport threading 227db96d56Sopenharmony_cifrom _weakrefset import WeakSet 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_ci# 257db96d56Sopenharmony_ci# 267db96d56Sopenharmony_ci# 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_citry: 297db96d56Sopenharmony_ci ORIGINAL_DIR = os.path.abspath(os.getcwd()) 307db96d56Sopenharmony_ciexcept OSError: 317db96d56Sopenharmony_ci ORIGINAL_DIR = None 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci# 347db96d56Sopenharmony_ci# Public functions 357db96d56Sopenharmony_ci# 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_cidef current_process(): 387db96d56Sopenharmony_ci ''' 397db96d56Sopenharmony_ci Return process object representing the current process 407db96d56Sopenharmony_ci ''' 417db96d56Sopenharmony_ci return _current_process 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_cidef active_children(): 447db96d56Sopenharmony_ci ''' 457db96d56Sopenharmony_ci Return list of process objects corresponding to live child processes 467db96d56Sopenharmony_ci ''' 477db96d56Sopenharmony_ci _cleanup() 487db96d56Sopenharmony_ci return list(_children) 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_cidef parent_process(): 527db96d56Sopenharmony_ci ''' 537db96d56Sopenharmony_ci Return process object representing the parent process 547db96d56Sopenharmony_ci ''' 557db96d56Sopenharmony_ci return _parent_process 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_ci# 587db96d56Sopenharmony_ci# 597db96d56Sopenharmony_ci# 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_cidef _cleanup(): 627db96d56Sopenharmony_ci # check for processes which have finished 637db96d56Sopenharmony_ci for p in list(_children): 647db96d56Sopenharmony_ci if (child_popen := p._popen) and child_popen.poll() is not None: 657db96d56Sopenharmony_ci _children.discard(p) 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci# 687db96d56Sopenharmony_ci# The `Process` class 697db96d56Sopenharmony_ci# 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ciclass BaseProcess(object): 727db96d56Sopenharmony_ci ''' 737db96d56Sopenharmony_ci Process objects represent activity that is run in a separate process 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci The class is analogous to `threading.Thread` 767db96d56Sopenharmony_ci ''' 777db96d56Sopenharmony_ci def _Popen(self): 787db96d56Sopenharmony_ci raise NotImplementedError 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, 817db96d56Sopenharmony_ci *, daemon=None): 827db96d56Sopenharmony_ci assert group is None, 'group argument must be None for now' 837db96d56Sopenharmony_ci count = next(_process_counter) 847db96d56Sopenharmony_ci self._identity = _current_process._identity + (count,) 857db96d56Sopenharmony_ci self._config = _current_process._config.copy() 867db96d56Sopenharmony_ci self._parent_pid = os.getpid() 877db96d56Sopenharmony_ci self._parent_name = _current_process.name 887db96d56Sopenharmony_ci self._popen = None 897db96d56Sopenharmony_ci self._closed = False 907db96d56Sopenharmony_ci self._target = target 917db96d56Sopenharmony_ci self._args = tuple(args) 927db96d56Sopenharmony_ci self._kwargs = dict(kwargs) 937db96d56Sopenharmony_ci self._name = name or type(self).__name__ + '-' + \ 947db96d56Sopenharmony_ci ':'.join(str(i) for i in self._identity) 957db96d56Sopenharmony_ci if daemon is not None: 967db96d56Sopenharmony_ci self.daemon = daemon 977db96d56Sopenharmony_ci _dangling.add(self) 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci def _check_closed(self): 1007db96d56Sopenharmony_ci if self._closed: 1017db96d56Sopenharmony_ci raise ValueError("process object is closed") 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci def run(self): 1047db96d56Sopenharmony_ci ''' 1057db96d56Sopenharmony_ci Method to be run in sub-process; can be overridden in sub-class 1067db96d56Sopenharmony_ci ''' 1077db96d56Sopenharmony_ci if self._target: 1087db96d56Sopenharmony_ci self._target(*self._args, **self._kwargs) 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci def start(self): 1117db96d56Sopenharmony_ci ''' 1127db96d56Sopenharmony_ci Start child process 1137db96d56Sopenharmony_ci ''' 1147db96d56Sopenharmony_ci self._check_closed() 1157db96d56Sopenharmony_ci assert self._popen is None, 'cannot start a process twice' 1167db96d56Sopenharmony_ci assert self._parent_pid == os.getpid(), \ 1177db96d56Sopenharmony_ci 'can only start a process object created by current process' 1187db96d56Sopenharmony_ci assert not _current_process._config.get('daemon'), \ 1197db96d56Sopenharmony_ci 'daemonic processes are not allowed to have children' 1207db96d56Sopenharmony_ci _cleanup() 1217db96d56Sopenharmony_ci self._popen = self._Popen(self) 1227db96d56Sopenharmony_ci self._sentinel = self._popen.sentinel 1237db96d56Sopenharmony_ci # Avoid a refcycle if the target function holds an indirect 1247db96d56Sopenharmony_ci # reference to the process object (see bpo-30775) 1257db96d56Sopenharmony_ci del self._target, self._args, self._kwargs 1267db96d56Sopenharmony_ci _children.add(self) 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci def terminate(self): 1297db96d56Sopenharmony_ci ''' 1307db96d56Sopenharmony_ci Terminate process; sends SIGTERM signal or uses TerminateProcess() 1317db96d56Sopenharmony_ci ''' 1327db96d56Sopenharmony_ci self._check_closed() 1337db96d56Sopenharmony_ci self._popen.terminate() 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci def kill(self): 1367db96d56Sopenharmony_ci ''' 1377db96d56Sopenharmony_ci Terminate process; sends SIGKILL signal or uses TerminateProcess() 1387db96d56Sopenharmony_ci ''' 1397db96d56Sopenharmony_ci self._check_closed() 1407db96d56Sopenharmony_ci self._popen.kill() 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci def join(self, timeout=None): 1437db96d56Sopenharmony_ci ''' 1447db96d56Sopenharmony_ci Wait until child process terminates 1457db96d56Sopenharmony_ci ''' 1467db96d56Sopenharmony_ci self._check_closed() 1477db96d56Sopenharmony_ci assert self._parent_pid == os.getpid(), 'can only join a child process' 1487db96d56Sopenharmony_ci assert self._popen is not None, 'can only join a started process' 1497db96d56Sopenharmony_ci res = self._popen.wait(timeout) 1507db96d56Sopenharmony_ci if res is not None: 1517db96d56Sopenharmony_ci _children.discard(self) 1527db96d56Sopenharmony_ci 1537db96d56Sopenharmony_ci def is_alive(self): 1547db96d56Sopenharmony_ci ''' 1557db96d56Sopenharmony_ci Return whether process is alive 1567db96d56Sopenharmony_ci ''' 1577db96d56Sopenharmony_ci self._check_closed() 1587db96d56Sopenharmony_ci if self is _current_process: 1597db96d56Sopenharmony_ci return True 1607db96d56Sopenharmony_ci assert self._parent_pid == os.getpid(), 'can only test a child process' 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci if self._popen is None: 1637db96d56Sopenharmony_ci return False 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci returncode = self._popen.poll() 1667db96d56Sopenharmony_ci if returncode is None: 1677db96d56Sopenharmony_ci return True 1687db96d56Sopenharmony_ci else: 1697db96d56Sopenharmony_ci _children.discard(self) 1707db96d56Sopenharmony_ci return False 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci def close(self): 1737db96d56Sopenharmony_ci ''' 1747db96d56Sopenharmony_ci Close the Process object. 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ci This method releases resources held by the Process object. It is 1777db96d56Sopenharmony_ci an error to call this method if the child process is still running. 1787db96d56Sopenharmony_ci ''' 1797db96d56Sopenharmony_ci if self._popen is not None: 1807db96d56Sopenharmony_ci if self._popen.poll() is None: 1817db96d56Sopenharmony_ci raise ValueError("Cannot close a process while it is still running. " 1827db96d56Sopenharmony_ci "You should first call join() or terminate().") 1837db96d56Sopenharmony_ci self._popen.close() 1847db96d56Sopenharmony_ci self._popen = None 1857db96d56Sopenharmony_ci del self._sentinel 1867db96d56Sopenharmony_ci _children.discard(self) 1877db96d56Sopenharmony_ci self._closed = True 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci @property 1907db96d56Sopenharmony_ci def name(self): 1917db96d56Sopenharmony_ci return self._name 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci @name.setter 1947db96d56Sopenharmony_ci def name(self, name): 1957db96d56Sopenharmony_ci assert isinstance(name, str), 'name must be a string' 1967db96d56Sopenharmony_ci self._name = name 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci @property 1997db96d56Sopenharmony_ci def daemon(self): 2007db96d56Sopenharmony_ci ''' 2017db96d56Sopenharmony_ci Return whether process is a daemon 2027db96d56Sopenharmony_ci ''' 2037db96d56Sopenharmony_ci return self._config.get('daemon', False) 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci @daemon.setter 2067db96d56Sopenharmony_ci def daemon(self, daemonic): 2077db96d56Sopenharmony_ci ''' 2087db96d56Sopenharmony_ci Set whether process is a daemon 2097db96d56Sopenharmony_ci ''' 2107db96d56Sopenharmony_ci assert self._popen is None, 'process has already started' 2117db96d56Sopenharmony_ci self._config['daemon'] = daemonic 2127db96d56Sopenharmony_ci 2137db96d56Sopenharmony_ci @property 2147db96d56Sopenharmony_ci def authkey(self): 2157db96d56Sopenharmony_ci return self._config['authkey'] 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci @authkey.setter 2187db96d56Sopenharmony_ci def authkey(self, authkey): 2197db96d56Sopenharmony_ci ''' 2207db96d56Sopenharmony_ci Set authorization key of process 2217db96d56Sopenharmony_ci ''' 2227db96d56Sopenharmony_ci self._config['authkey'] = AuthenticationString(authkey) 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci @property 2257db96d56Sopenharmony_ci def exitcode(self): 2267db96d56Sopenharmony_ci ''' 2277db96d56Sopenharmony_ci Return exit code of process or `None` if it has yet to stop 2287db96d56Sopenharmony_ci ''' 2297db96d56Sopenharmony_ci self._check_closed() 2307db96d56Sopenharmony_ci if self._popen is None: 2317db96d56Sopenharmony_ci return self._popen 2327db96d56Sopenharmony_ci return self._popen.poll() 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci @property 2357db96d56Sopenharmony_ci def ident(self): 2367db96d56Sopenharmony_ci ''' 2377db96d56Sopenharmony_ci Return identifier (PID) of process or `None` if it has yet to start 2387db96d56Sopenharmony_ci ''' 2397db96d56Sopenharmony_ci self._check_closed() 2407db96d56Sopenharmony_ci if self is _current_process: 2417db96d56Sopenharmony_ci return os.getpid() 2427db96d56Sopenharmony_ci else: 2437db96d56Sopenharmony_ci return self._popen and self._popen.pid 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci pid = ident 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci @property 2487db96d56Sopenharmony_ci def sentinel(self): 2497db96d56Sopenharmony_ci ''' 2507db96d56Sopenharmony_ci Return a file descriptor (Unix) or handle (Windows) suitable for 2517db96d56Sopenharmony_ci waiting for process termination. 2527db96d56Sopenharmony_ci ''' 2537db96d56Sopenharmony_ci self._check_closed() 2547db96d56Sopenharmony_ci try: 2557db96d56Sopenharmony_ci return self._sentinel 2567db96d56Sopenharmony_ci except AttributeError: 2577db96d56Sopenharmony_ci raise ValueError("process not started") from None 2587db96d56Sopenharmony_ci 2597db96d56Sopenharmony_ci def __repr__(self): 2607db96d56Sopenharmony_ci exitcode = None 2617db96d56Sopenharmony_ci if self is _current_process: 2627db96d56Sopenharmony_ci status = 'started' 2637db96d56Sopenharmony_ci elif self._closed: 2647db96d56Sopenharmony_ci status = 'closed' 2657db96d56Sopenharmony_ci elif self._parent_pid != os.getpid(): 2667db96d56Sopenharmony_ci status = 'unknown' 2677db96d56Sopenharmony_ci elif self._popen is None: 2687db96d56Sopenharmony_ci status = 'initial' 2697db96d56Sopenharmony_ci else: 2707db96d56Sopenharmony_ci exitcode = self._popen.poll() 2717db96d56Sopenharmony_ci if exitcode is not None: 2727db96d56Sopenharmony_ci status = 'stopped' 2737db96d56Sopenharmony_ci else: 2747db96d56Sopenharmony_ci status = 'started' 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ci info = [type(self).__name__, 'name=%r' % self._name] 2777db96d56Sopenharmony_ci if self._popen is not None: 2787db96d56Sopenharmony_ci info.append('pid=%s' % self._popen.pid) 2797db96d56Sopenharmony_ci info.append('parent=%s' % self._parent_pid) 2807db96d56Sopenharmony_ci info.append(status) 2817db96d56Sopenharmony_ci if exitcode is not None: 2827db96d56Sopenharmony_ci exitcode = _exitcode_to_name.get(exitcode, exitcode) 2837db96d56Sopenharmony_ci info.append('exitcode=%s' % exitcode) 2847db96d56Sopenharmony_ci if self.daemon: 2857db96d56Sopenharmony_ci info.append('daemon') 2867db96d56Sopenharmony_ci return '<%s>' % ' '.join(info) 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci ## 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_ci def _bootstrap(self, parent_sentinel=None): 2917db96d56Sopenharmony_ci from . import util, context 2927db96d56Sopenharmony_ci global _current_process, _parent_process, _process_counter, _children 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci try: 2957db96d56Sopenharmony_ci if self._start_method is not None: 2967db96d56Sopenharmony_ci context._force_start_method(self._start_method) 2977db96d56Sopenharmony_ci _process_counter = itertools.count(1) 2987db96d56Sopenharmony_ci _children = set() 2997db96d56Sopenharmony_ci util._close_stdin() 3007db96d56Sopenharmony_ci old_process = _current_process 3017db96d56Sopenharmony_ci _current_process = self 3027db96d56Sopenharmony_ci _parent_process = _ParentProcess( 3037db96d56Sopenharmony_ci self._parent_name, self._parent_pid, parent_sentinel) 3047db96d56Sopenharmony_ci if threading._HAVE_THREAD_NATIVE_ID: 3057db96d56Sopenharmony_ci threading.main_thread()._set_native_id() 3067db96d56Sopenharmony_ci try: 3077db96d56Sopenharmony_ci self._after_fork() 3087db96d56Sopenharmony_ci finally: 3097db96d56Sopenharmony_ci # delay finalization of the old process object until after 3107db96d56Sopenharmony_ci # _run_after_forkers() is executed 3117db96d56Sopenharmony_ci del old_process 3127db96d56Sopenharmony_ci util.info('child process calling self.run()') 3137db96d56Sopenharmony_ci try: 3147db96d56Sopenharmony_ci self.run() 3157db96d56Sopenharmony_ci exitcode = 0 3167db96d56Sopenharmony_ci finally: 3177db96d56Sopenharmony_ci util._exit_function() 3187db96d56Sopenharmony_ci except SystemExit as e: 3197db96d56Sopenharmony_ci if e.code is None: 3207db96d56Sopenharmony_ci exitcode = 0 3217db96d56Sopenharmony_ci elif isinstance(e.code, int): 3227db96d56Sopenharmony_ci exitcode = e.code 3237db96d56Sopenharmony_ci else: 3247db96d56Sopenharmony_ci sys.stderr.write(str(e.code) + '\n') 3257db96d56Sopenharmony_ci exitcode = 1 3267db96d56Sopenharmony_ci except: 3277db96d56Sopenharmony_ci exitcode = 1 3287db96d56Sopenharmony_ci import traceback 3297db96d56Sopenharmony_ci sys.stderr.write('Process %s:\n' % self.name) 3307db96d56Sopenharmony_ci traceback.print_exc() 3317db96d56Sopenharmony_ci finally: 3327db96d56Sopenharmony_ci threading._shutdown() 3337db96d56Sopenharmony_ci util.info('process exiting with exitcode %d' % exitcode) 3347db96d56Sopenharmony_ci util._flush_std_streams() 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci return exitcode 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_ci @staticmethod 3397db96d56Sopenharmony_ci def _after_fork(): 3407db96d56Sopenharmony_ci from . import util 3417db96d56Sopenharmony_ci util._finalizer_registry.clear() 3427db96d56Sopenharmony_ci util._run_after_forkers() 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci# 3467db96d56Sopenharmony_ci# We subclass bytes to avoid accidental transmission of auth keys over network 3477db96d56Sopenharmony_ci# 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ciclass AuthenticationString(bytes): 3507db96d56Sopenharmony_ci def __reduce__(self): 3517db96d56Sopenharmony_ci from .context import get_spawning_popen 3527db96d56Sopenharmony_ci if get_spawning_popen() is None: 3537db96d56Sopenharmony_ci raise TypeError( 3547db96d56Sopenharmony_ci 'Pickling an AuthenticationString object is ' 3557db96d56Sopenharmony_ci 'disallowed for security reasons' 3567db96d56Sopenharmony_ci ) 3577db96d56Sopenharmony_ci return AuthenticationString, (bytes(self),) 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci 3607db96d56Sopenharmony_ci# 3617db96d56Sopenharmony_ci# Create object representing the parent process 3627db96d56Sopenharmony_ci# 3637db96d56Sopenharmony_ci 3647db96d56Sopenharmony_ciclass _ParentProcess(BaseProcess): 3657db96d56Sopenharmony_ci 3667db96d56Sopenharmony_ci def __init__(self, name, pid, sentinel): 3677db96d56Sopenharmony_ci self._identity = () 3687db96d56Sopenharmony_ci self._name = name 3697db96d56Sopenharmony_ci self._pid = pid 3707db96d56Sopenharmony_ci self._parent_pid = None 3717db96d56Sopenharmony_ci self._popen = None 3727db96d56Sopenharmony_ci self._closed = False 3737db96d56Sopenharmony_ci self._sentinel = sentinel 3747db96d56Sopenharmony_ci self._config = {} 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci def is_alive(self): 3777db96d56Sopenharmony_ci from multiprocessing.connection import wait 3787db96d56Sopenharmony_ci return not wait([self._sentinel], timeout=0) 3797db96d56Sopenharmony_ci 3807db96d56Sopenharmony_ci @property 3817db96d56Sopenharmony_ci def ident(self): 3827db96d56Sopenharmony_ci return self._pid 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci def join(self, timeout=None): 3857db96d56Sopenharmony_ci ''' 3867db96d56Sopenharmony_ci Wait until parent process terminates 3877db96d56Sopenharmony_ci ''' 3887db96d56Sopenharmony_ci from multiprocessing.connection import wait 3897db96d56Sopenharmony_ci wait([self._sentinel], timeout=timeout) 3907db96d56Sopenharmony_ci 3917db96d56Sopenharmony_ci pid = ident 3927db96d56Sopenharmony_ci 3937db96d56Sopenharmony_ci# 3947db96d56Sopenharmony_ci# Create object representing the main process 3957db96d56Sopenharmony_ci# 3967db96d56Sopenharmony_ci 3977db96d56Sopenharmony_ciclass _MainProcess(BaseProcess): 3987db96d56Sopenharmony_ci 3997db96d56Sopenharmony_ci def __init__(self): 4007db96d56Sopenharmony_ci self._identity = () 4017db96d56Sopenharmony_ci self._name = 'MainProcess' 4027db96d56Sopenharmony_ci self._parent_pid = None 4037db96d56Sopenharmony_ci self._popen = None 4047db96d56Sopenharmony_ci self._closed = False 4057db96d56Sopenharmony_ci self._config = {'authkey': AuthenticationString(os.urandom(32)), 4067db96d56Sopenharmony_ci 'semprefix': '/mp'} 4077db96d56Sopenharmony_ci # Note that some versions of FreeBSD only allow named 4087db96d56Sopenharmony_ci # semaphores to have names of up to 14 characters. Therefore 4097db96d56Sopenharmony_ci # we choose a short prefix. 4107db96d56Sopenharmony_ci # 4117db96d56Sopenharmony_ci # On MacOSX in a sandbox it may be necessary to use a 4127db96d56Sopenharmony_ci # different prefix -- see #19478. 4137db96d56Sopenharmony_ci # 4147db96d56Sopenharmony_ci # Everything in self._config will be inherited by descendant 4157db96d56Sopenharmony_ci # processes. 4167db96d56Sopenharmony_ci 4177db96d56Sopenharmony_ci def close(self): 4187db96d56Sopenharmony_ci pass 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ci 4217db96d56Sopenharmony_ci_parent_process = None 4227db96d56Sopenharmony_ci_current_process = _MainProcess() 4237db96d56Sopenharmony_ci_process_counter = itertools.count(1) 4247db96d56Sopenharmony_ci_children = set() 4257db96d56Sopenharmony_cidel _MainProcess 4267db96d56Sopenharmony_ci 4277db96d56Sopenharmony_ci# 4287db96d56Sopenharmony_ci# Give names to some return codes 4297db96d56Sopenharmony_ci# 4307db96d56Sopenharmony_ci 4317db96d56Sopenharmony_ci_exitcode_to_name = {} 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_cifor name, signum in list(signal.__dict__.items()): 4347db96d56Sopenharmony_ci if name[:3]=='SIG' and '_' not in name: 4357db96d56Sopenharmony_ci _exitcode_to_name[-signum] = f'-{name}' 4367db96d56Sopenharmony_cidel name, signum 4377db96d56Sopenharmony_ci 4387db96d56Sopenharmony_ci# For debug and leak testing 4397db96d56Sopenharmony_ci_dangling = WeakSet() 440