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