xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/multiprocessing/process.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker#
2*cda5da8dSAndroid Build Coastguard Worker# Module providing the `Process` class which emulates `threading.Thread`
3*cda5da8dSAndroid Build Coastguard Worker#
4*cda5da8dSAndroid Build Coastguard Worker# multiprocessing/process.py
5*cda5da8dSAndroid Build Coastguard Worker#
6*cda5da8dSAndroid Build Coastguard Worker# Copyright (c) 2006-2008, R Oudkerk
7*cda5da8dSAndroid Build Coastguard Worker# Licensed to PSF under a Contributor Agreement.
8*cda5da8dSAndroid Build Coastguard Worker#
9*cda5da8dSAndroid Build Coastguard Worker
10*cda5da8dSAndroid Build Coastguard Worker__all__ = ['BaseProcess', 'current_process', 'active_children',
11*cda5da8dSAndroid Build Coastguard Worker           'parent_process']
12*cda5da8dSAndroid Build Coastguard Worker
13*cda5da8dSAndroid Build Coastguard Worker#
14*cda5da8dSAndroid Build Coastguard Worker# Imports
15*cda5da8dSAndroid Build Coastguard Worker#
16*cda5da8dSAndroid Build Coastguard Worker
17*cda5da8dSAndroid Build Coastguard Workerimport os
18*cda5da8dSAndroid Build Coastguard Workerimport sys
19*cda5da8dSAndroid Build Coastguard Workerimport signal
20*cda5da8dSAndroid Build Coastguard Workerimport itertools
21*cda5da8dSAndroid Build Coastguard Workerimport threading
22*cda5da8dSAndroid Build Coastguard Workerfrom _weakrefset import WeakSet
23*cda5da8dSAndroid Build Coastguard Worker
24*cda5da8dSAndroid Build Coastguard Worker#
25*cda5da8dSAndroid Build Coastguard Worker#
26*cda5da8dSAndroid Build Coastguard Worker#
27*cda5da8dSAndroid Build Coastguard Worker
28*cda5da8dSAndroid Build Coastguard Workertry:
29*cda5da8dSAndroid Build Coastguard Worker    ORIGINAL_DIR = os.path.abspath(os.getcwd())
30*cda5da8dSAndroid Build Coastguard Workerexcept OSError:
31*cda5da8dSAndroid Build Coastguard Worker    ORIGINAL_DIR = None
32*cda5da8dSAndroid Build Coastguard Worker
33*cda5da8dSAndroid Build Coastguard Worker#
34*cda5da8dSAndroid Build Coastguard Worker# Public functions
35*cda5da8dSAndroid Build Coastguard Worker#
36*cda5da8dSAndroid Build Coastguard Worker
37*cda5da8dSAndroid Build Coastguard Workerdef current_process():
38*cda5da8dSAndroid Build Coastguard Worker    '''
39*cda5da8dSAndroid Build Coastguard Worker    Return process object representing the current process
40*cda5da8dSAndroid Build Coastguard Worker    '''
41*cda5da8dSAndroid Build Coastguard Worker    return _current_process
42*cda5da8dSAndroid Build Coastguard Worker
43*cda5da8dSAndroid Build Coastguard Workerdef active_children():
44*cda5da8dSAndroid Build Coastguard Worker    '''
45*cda5da8dSAndroid Build Coastguard Worker    Return list of process objects corresponding to live child processes
46*cda5da8dSAndroid Build Coastguard Worker    '''
47*cda5da8dSAndroid Build Coastguard Worker    _cleanup()
48*cda5da8dSAndroid Build Coastguard Worker    return list(_children)
49*cda5da8dSAndroid Build Coastguard Worker
50*cda5da8dSAndroid Build Coastguard Worker
51*cda5da8dSAndroid Build Coastguard Workerdef parent_process():
52*cda5da8dSAndroid Build Coastguard Worker    '''
53*cda5da8dSAndroid Build Coastguard Worker    Return process object representing the parent process
54*cda5da8dSAndroid Build Coastguard Worker    '''
55*cda5da8dSAndroid Build Coastguard Worker    return _parent_process
56*cda5da8dSAndroid Build Coastguard Worker
57*cda5da8dSAndroid Build Coastguard Worker#
58*cda5da8dSAndroid Build Coastguard Worker#
59*cda5da8dSAndroid Build Coastguard Worker#
60*cda5da8dSAndroid Build Coastguard Worker
61*cda5da8dSAndroid Build Coastguard Workerdef _cleanup():
62*cda5da8dSAndroid Build Coastguard Worker    # check for processes which have finished
63*cda5da8dSAndroid Build Coastguard Worker    for p in list(_children):
64*cda5da8dSAndroid Build Coastguard Worker        if (child_popen := p._popen) and child_popen.poll() is not None:
65*cda5da8dSAndroid Build Coastguard Worker            _children.discard(p)
66*cda5da8dSAndroid Build Coastguard Worker
67*cda5da8dSAndroid Build Coastguard Worker#
68*cda5da8dSAndroid Build Coastguard Worker# The `Process` class
69*cda5da8dSAndroid Build Coastguard Worker#
70*cda5da8dSAndroid Build Coastguard Worker
71*cda5da8dSAndroid Build Coastguard Workerclass BaseProcess(object):
72*cda5da8dSAndroid Build Coastguard Worker    '''
73*cda5da8dSAndroid Build Coastguard Worker    Process objects represent activity that is run in a separate process
74*cda5da8dSAndroid Build Coastguard Worker
75*cda5da8dSAndroid Build Coastguard Worker    The class is analogous to `threading.Thread`
76*cda5da8dSAndroid Build Coastguard Worker    '''
77*cda5da8dSAndroid Build Coastguard Worker    def _Popen(self):
78*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
79*cda5da8dSAndroid Build Coastguard Worker
80*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
81*cda5da8dSAndroid Build Coastguard Worker                 *, daemon=None):
82*cda5da8dSAndroid Build Coastguard Worker        assert group is None, 'group argument must be None for now'
83*cda5da8dSAndroid Build Coastguard Worker        count = next(_process_counter)
84*cda5da8dSAndroid Build Coastguard Worker        self._identity = _current_process._identity + (count,)
85*cda5da8dSAndroid Build Coastguard Worker        self._config = _current_process._config.copy()
86*cda5da8dSAndroid Build Coastguard Worker        self._parent_pid = os.getpid()
87*cda5da8dSAndroid Build Coastguard Worker        self._parent_name = _current_process.name
88*cda5da8dSAndroid Build Coastguard Worker        self._popen = None
89*cda5da8dSAndroid Build Coastguard Worker        self._closed = False
90*cda5da8dSAndroid Build Coastguard Worker        self._target = target
91*cda5da8dSAndroid Build Coastguard Worker        self._args = tuple(args)
92*cda5da8dSAndroid Build Coastguard Worker        self._kwargs = dict(kwargs)
93*cda5da8dSAndroid Build Coastguard Worker        self._name = name or type(self).__name__ + '-' + \
94*cda5da8dSAndroid Build Coastguard Worker                     ':'.join(str(i) for i in self._identity)
95*cda5da8dSAndroid Build Coastguard Worker        if daemon is not None:
96*cda5da8dSAndroid Build Coastguard Worker            self.daemon = daemon
97*cda5da8dSAndroid Build Coastguard Worker        _dangling.add(self)
98*cda5da8dSAndroid Build Coastguard Worker
99*cda5da8dSAndroid Build Coastguard Worker    def _check_closed(self):
100*cda5da8dSAndroid Build Coastguard Worker        if self._closed:
101*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("process object is closed")
102*cda5da8dSAndroid Build Coastguard Worker
103*cda5da8dSAndroid Build Coastguard Worker    def run(self):
104*cda5da8dSAndroid Build Coastguard Worker        '''
105*cda5da8dSAndroid Build Coastguard Worker        Method to be run in sub-process; can be overridden in sub-class
106*cda5da8dSAndroid Build Coastguard Worker        '''
107*cda5da8dSAndroid Build Coastguard Worker        if self._target:
108*cda5da8dSAndroid Build Coastguard Worker            self._target(*self._args, **self._kwargs)
109*cda5da8dSAndroid Build Coastguard Worker
110*cda5da8dSAndroid Build Coastguard Worker    def start(self):
111*cda5da8dSAndroid Build Coastguard Worker        '''
112*cda5da8dSAndroid Build Coastguard Worker        Start child process
113*cda5da8dSAndroid Build Coastguard Worker        '''
114*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
115*cda5da8dSAndroid Build Coastguard Worker        assert self._popen is None, 'cannot start a process twice'
116*cda5da8dSAndroid Build Coastguard Worker        assert self._parent_pid == os.getpid(), \
117*cda5da8dSAndroid Build Coastguard Worker               'can only start a process object created by current process'
118*cda5da8dSAndroid Build Coastguard Worker        assert not _current_process._config.get('daemon'), \
119*cda5da8dSAndroid Build Coastguard Worker               'daemonic processes are not allowed to have children'
120*cda5da8dSAndroid Build Coastguard Worker        _cleanup()
121*cda5da8dSAndroid Build Coastguard Worker        self._popen = self._Popen(self)
122*cda5da8dSAndroid Build Coastguard Worker        self._sentinel = self._popen.sentinel
123*cda5da8dSAndroid Build Coastguard Worker        # Avoid a refcycle if the target function holds an indirect
124*cda5da8dSAndroid Build Coastguard Worker        # reference to the process object (see bpo-30775)
125*cda5da8dSAndroid Build Coastguard Worker        del self._target, self._args, self._kwargs
126*cda5da8dSAndroid Build Coastguard Worker        _children.add(self)
127*cda5da8dSAndroid Build Coastguard Worker
128*cda5da8dSAndroid Build Coastguard Worker    def terminate(self):
129*cda5da8dSAndroid Build Coastguard Worker        '''
130*cda5da8dSAndroid Build Coastguard Worker        Terminate process; sends SIGTERM signal or uses TerminateProcess()
131*cda5da8dSAndroid Build Coastguard Worker        '''
132*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
133*cda5da8dSAndroid Build Coastguard Worker        self._popen.terminate()
134*cda5da8dSAndroid Build Coastguard Worker
135*cda5da8dSAndroid Build Coastguard Worker    def kill(self):
136*cda5da8dSAndroid Build Coastguard Worker        '''
137*cda5da8dSAndroid Build Coastguard Worker        Terminate process; sends SIGKILL signal or uses TerminateProcess()
138*cda5da8dSAndroid Build Coastguard Worker        '''
139*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
140*cda5da8dSAndroid Build Coastguard Worker        self._popen.kill()
141*cda5da8dSAndroid Build Coastguard Worker
142*cda5da8dSAndroid Build Coastguard Worker    def join(self, timeout=None):
143*cda5da8dSAndroid Build Coastguard Worker        '''
144*cda5da8dSAndroid Build Coastguard Worker        Wait until child process terminates
145*cda5da8dSAndroid Build Coastguard Worker        '''
146*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
147*cda5da8dSAndroid Build Coastguard Worker        assert self._parent_pid == os.getpid(), 'can only join a child process'
148*cda5da8dSAndroid Build Coastguard Worker        assert self._popen is not None, 'can only join a started process'
149*cda5da8dSAndroid Build Coastguard Worker        res = self._popen.wait(timeout)
150*cda5da8dSAndroid Build Coastguard Worker        if res is not None:
151*cda5da8dSAndroid Build Coastguard Worker            _children.discard(self)
152*cda5da8dSAndroid Build Coastguard Worker
153*cda5da8dSAndroid Build Coastguard Worker    def is_alive(self):
154*cda5da8dSAndroid Build Coastguard Worker        '''
155*cda5da8dSAndroid Build Coastguard Worker        Return whether process is alive
156*cda5da8dSAndroid Build Coastguard Worker        '''
157*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
158*cda5da8dSAndroid Build Coastguard Worker        if self is _current_process:
159*cda5da8dSAndroid Build Coastguard Worker            return True
160*cda5da8dSAndroid Build Coastguard Worker        assert self._parent_pid == os.getpid(), 'can only test a child process'
161*cda5da8dSAndroid Build Coastguard Worker
162*cda5da8dSAndroid Build Coastguard Worker        if self._popen is None:
163*cda5da8dSAndroid Build Coastguard Worker            return False
164*cda5da8dSAndroid Build Coastguard Worker
165*cda5da8dSAndroid Build Coastguard Worker        returncode = self._popen.poll()
166*cda5da8dSAndroid Build Coastguard Worker        if returncode is None:
167*cda5da8dSAndroid Build Coastguard Worker            return True
168*cda5da8dSAndroid Build Coastguard Worker        else:
169*cda5da8dSAndroid Build Coastguard Worker            _children.discard(self)
170*cda5da8dSAndroid Build Coastguard Worker            return False
171*cda5da8dSAndroid Build Coastguard Worker
172*cda5da8dSAndroid Build Coastguard Worker    def close(self):
173*cda5da8dSAndroid Build Coastguard Worker        '''
174*cda5da8dSAndroid Build Coastguard Worker        Close the Process object.
175*cda5da8dSAndroid Build Coastguard Worker
176*cda5da8dSAndroid Build Coastguard Worker        This method releases resources held by the Process object.  It is
177*cda5da8dSAndroid Build Coastguard Worker        an error to call this method if the child process is still running.
178*cda5da8dSAndroid Build Coastguard Worker        '''
179*cda5da8dSAndroid Build Coastguard Worker        if self._popen is not None:
180*cda5da8dSAndroid Build Coastguard Worker            if self._popen.poll() is None:
181*cda5da8dSAndroid Build Coastguard Worker                raise ValueError("Cannot close a process while it is still running. "
182*cda5da8dSAndroid Build Coastguard Worker                                 "You should first call join() or terminate().")
183*cda5da8dSAndroid Build Coastguard Worker            self._popen.close()
184*cda5da8dSAndroid Build Coastguard Worker            self._popen = None
185*cda5da8dSAndroid Build Coastguard Worker            del self._sentinel
186*cda5da8dSAndroid Build Coastguard Worker            _children.discard(self)
187*cda5da8dSAndroid Build Coastguard Worker        self._closed = True
188*cda5da8dSAndroid Build Coastguard Worker
189*cda5da8dSAndroid Build Coastguard Worker    @property
190*cda5da8dSAndroid Build Coastguard Worker    def name(self):
191*cda5da8dSAndroid Build Coastguard Worker        return self._name
192*cda5da8dSAndroid Build Coastguard Worker
193*cda5da8dSAndroid Build Coastguard Worker    @name.setter
194*cda5da8dSAndroid Build Coastguard Worker    def name(self, name):
195*cda5da8dSAndroid Build Coastguard Worker        assert isinstance(name, str), 'name must be a string'
196*cda5da8dSAndroid Build Coastguard Worker        self._name = name
197*cda5da8dSAndroid Build Coastguard Worker
198*cda5da8dSAndroid Build Coastguard Worker    @property
199*cda5da8dSAndroid Build Coastguard Worker    def daemon(self):
200*cda5da8dSAndroid Build Coastguard Worker        '''
201*cda5da8dSAndroid Build Coastguard Worker        Return whether process is a daemon
202*cda5da8dSAndroid Build Coastguard Worker        '''
203*cda5da8dSAndroid Build Coastguard Worker        return self._config.get('daemon', False)
204*cda5da8dSAndroid Build Coastguard Worker
205*cda5da8dSAndroid Build Coastguard Worker    @daemon.setter
206*cda5da8dSAndroid Build Coastguard Worker    def daemon(self, daemonic):
207*cda5da8dSAndroid Build Coastguard Worker        '''
208*cda5da8dSAndroid Build Coastguard Worker        Set whether process is a daemon
209*cda5da8dSAndroid Build Coastguard Worker        '''
210*cda5da8dSAndroid Build Coastguard Worker        assert self._popen is None, 'process has already started'
211*cda5da8dSAndroid Build Coastguard Worker        self._config['daemon'] = daemonic
212*cda5da8dSAndroid Build Coastguard Worker
213*cda5da8dSAndroid Build Coastguard Worker    @property
214*cda5da8dSAndroid Build Coastguard Worker    def authkey(self):
215*cda5da8dSAndroid Build Coastguard Worker        return self._config['authkey']
216*cda5da8dSAndroid Build Coastguard Worker
217*cda5da8dSAndroid Build Coastguard Worker    @authkey.setter
218*cda5da8dSAndroid Build Coastguard Worker    def authkey(self, authkey):
219*cda5da8dSAndroid Build Coastguard Worker        '''
220*cda5da8dSAndroid Build Coastguard Worker        Set authorization key of process
221*cda5da8dSAndroid Build Coastguard Worker        '''
222*cda5da8dSAndroid Build Coastguard Worker        self._config['authkey'] = AuthenticationString(authkey)
223*cda5da8dSAndroid Build Coastguard Worker
224*cda5da8dSAndroid Build Coastguard Worker    @property
225*cda5da8dSAndroid Build Coastguard Worker    def exitcode(self):
226*cda5da8dSAndroid Build Coastguard Worker        '''
227*cda5da8dSAndroid Build Coastguard Worker        Return exit code of process or `None` if it has yet to stop
228*cda5da8dSAndroid Build Coastguard Worker        '''
229*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
230*cda5da8dSAndroid Build Coastguard Worker        if self._popen is None:
231*cda5da8dSAndroid Build Coastguard Worker            return self._popen
232*cda5da8dSAndroid Build Coastguard Worker        return self._popen.poll()
233*cda5da8dSAndroid Build Coastguard Worker
234*cda5da8dSAndroid Build Coastguard Worker    @property
235*cda5da8dSAndroid Build Coastguard Worker    def ident(self):
236*cda5da8dSAndroid Build Coastguard Worker        '''
237*cda5da8dSAndroid Build Coastguard Worker        Return identifier (PID) of process or `None` if it has yet to start
238*cda5da8dSAndroid Build Coastguard Worker        '''
239*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
240*cda5da8dSAndroid Build Coastguard Worker        if self is _current_process:
241*cda5da8dSAndroid Build Coastguard Worker            return os.getpid()
242*cda5da8dSAndroid Build Coastguard Worker        else:
243*cda5da8dSAndroid Build Coastguard Worker            return self._popen and self._popen.pid
244*cda5da8dSAndroid Build Coastguard Worker
245*cda5da8dSAndroid Build Coastguard Worker    pid = ident
246*cda5da8dSAndroid Build Coastguard Worker
247*cda5da8dSAndroid Build Coastguard Worker    @property
248*cda5da8dSAndroid Build Coastguard Worker    def sentinel(self):
249*cda5da8dSAndroid Build Coastguard Worker        '''
250*cda5da8dSAndroid Build Coastguard Worker        Return a file descriptor (Unix) or handle (Windows) suitable for
251*cda5da8dSAndroid Build Coastguard Worker        waiting for process termination.
252*cda5da8dSAndroid Build Coastguard Worker        '''
253*cda5da8dSAndroid Build Coastguard Worker        self._check_closed()
254*cda5da8dSAndroid Build Coastguard Worker        try:
255*cda5da8dSAndroid Build Coastguard Worker            return self._sentinel
256*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
257*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("process not started") from None
258*cda5da8dSAndroid Build Coastguard Worker
259*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
260*cda5da8dSAndroid Build Coastguard Worker        exitcode = None
261*cda5da8dSAndroid Build Coastguard Worker        if self is _current_process:
262*cda5da8dSAndroid Build Coastguard Worker            status = 'started'
263*cda5da8dSAndroid Build Coastguard Worker        elif self._closed:
264*cda5da8dSAndroid Build Coastguard Worker            status = 'closed'
265*cda5da8dSAndroid Build Coastguard Worker        elif self._parent_pid != os.getpid():
266*cda5da8dSAndroid Build Coastguard Worker            status = 'unknown'
267*cda5da8dSAndroid Build Coastguard Worker        elif self._popen is None:
268*cda5da8dSAndroid Build Coastguard Worker            status = 'initial'
269*cda5da8dSAndroid Build Coastguard Worker        else:
270*cda5da8dSAndroid Build Coastguard Worker            exitcode = self._popen.poll()
271*cda5da8dSAndroid Build Coastguard Worker            if exitcode is not None:
272*cda5da8dSAndroid Build Coastguard Worker                status = 'stopped'
273*cda5da8dSAndroid Build Coastguard Worker            else:
274*cda5da8dSAndroid Build Coastguard Worker                status = 'started'
275*cda5da8dSAndroid Build Coastguard Worker
276*cda5da8dSAndroid Build Coastguard Worker        info = [type(self).__name__, 'name=%r' % self._name]
277*cda5da8dSAndroid Build Coastguard Worker        if self._popen is not None:
278*cda5da8dSAndroid Build Coastguard Worker            info.append('pid=%s' % self._popen.pid)
279*cda5da8dSAndroid Build Coastguard Worker        info.append('parent=%s' % self._parent_pid)
280*cda5da8dSAndroid Build Coastguard Worker        info.append(status)
281*cda5da8dSAndroid Build Coastguard Worker        if exitcode is not None:
282*cda5da8dSAndroid Build Coastguard Worker            exitcode = _exitcode_to_name.get(exitcode, exitcode)
283*cda5da8dSAndroid Build Coastguard Worker            info.append('exitcode=%s' % exitcode)
284*cda5da8dSAndroid Build Coastguard Worker        if self.daemon:
285*cda5da8dSAndroid Build Coastguard Worker            info.append('daemon')
286*cda5da8dSAndroid Build Coastguard Worker        return '<%s>' % ' '.join(info)
287*cda5da8dSAndroid Build Coastguard Worker
288*cda5da8dSAndroid Build Coastguard Worker    ##
289*cda5da8dSAndroid Build Coastguard Worker
290*cda5da8dSAndroid Build Coastguard Worker    def _bootstrap(self, parent_sentinel=None):
291*cda5da8dSAndroid Build Coastguard Worker        from . import util, context
292*cda5da8dSAndroid Build Coastguard Worker        global _current_process, _parent_process, _process_counter, _children
293*cda5da8dSAndroid Build Coastguard Worker
294*cda5da8dSAndroid Build Coastguard Worker        try:
295*cda5da8dSAndroid Build Coastguard Worker            if self._start_method is not None:
296*cda5da8dSAndroid Build Coastguard Worker                context._force_start_method(self._start_method)
297*cda5da8dSAndroid Build Coastguard Worker            _process_counter = itertools.count(1)
298*cda5da8dSAndroid Build Coastguard Worker            _children = set()
299*cda5da8dSAndroid Build Coastguard Worker            util._close_stdin()
300*cda5da8dSAndroid Build Coastguard Worker            old_process = _current_process
301*cda5da8dSAndroid Build Coastguard Worker            _current_process = self
302*cda5da8dSAndroid Build Coastguard Worker            _parent_process = _ParentProcess(
303*cda5da8dSAndroid Build Coastguard Worker                self._parent_name, self._parent_pid, parent_sentinel)
304*cda5da8dSAndroid Build Coastguard Worker            if threading._HAVE_THREAD_NATIVE_ID:
305*cda5da8dSAndroid Build Coastguard Worker                threading.main_thread()._set_native_id()
306*cda5da8dSAndroid Build Coastguard Worker            try:
307*cda5da8dSAndroid Build Coastguard Worker                self._after_fork()
308*cda5da8dSAndroid Build Coastguard Worker            finally:
309*cda5da8dSAndroid Build Coastguard Worker                # delay finalization of the old process object until after
310*cda5da8dSAndroid Build Coastguard Worker                # _run_after_forkers() is executed
311*cda5da8dSAndroid Build Coastguard Worker                del old_process
312*cda5da8dSAndroid Build Coastguard Worker            util.info('child process calling self.run()')
313*cda5da8dSAndroid Build Coastguard Worker            try:
314*cda5da8dSAndroid Build Coastguard Worker                self.run()
315*cda5da8dSAndroid Build Coastguard Worker                exitcode = 0
316*cda5da8dSAndroid Build Coastguard Worker            finally:
317*cda5da8dSAndroid Build Coastguard Worker                util._exit_function()
318*cda5da8dSAndroid Build Coastguard Worker        except SystemExit as e:
319*cda5da8dSAndroid Build Coastguard Worker            if e.code is None:
320*cda5da8dSAndroid Build Coastguard Worker                exitcode = 0
321*cda5da8dSAndroid Build Coastguard Worker            elif isinstance(e.code, int):
322*cda5da8dSAndroid Build Coastguard Worker                exitcode = e.code
323*cda5da8dSAndroid Build Coastguard Worker            else:
324*cda5da8dSAndroid Build Coastguard Worker                sys.stderr.write(str(e.code) + '\n')
325*cda5da8dSAndroid Build Coastguard Worker                exitcode = 1
326*cda5da8dSAndroid Build Coastguard Worker        except:
327*cda5da8dSAndroid Build Coastguard Worker            exitcode = 1
328*cda5da8dSAndroid Build Coastguard Worker            import traceback
329*cda5da8dSAndroid Build Coastguard Worker            sys.stderr.write('Process %s:\n' % self.name)
330*cda5da8dSAndroid Build Coastguard Worker            traceback.print_exc()
331*cda5da8dSAndroid Build Coastguard Worker        finally:
332*cda5da8dSAndroid Build Coastguard Worker            threading._shutdown()
333*cda5da8dSAndroid Build Coastguard Worker            util.info('process exiting with exitcode %d' % exitcode)
334*cda5da8dSAndroid Build Coastguard Worker            util._flush_std_streams()
335*cda5da8dSAndroid Build Coastguard Worker
336*cda5da8dSAndroid Build Coastguard Worker        return exitcode
337*cda5da8dSAndroid Build Coastguard Worker
338*cda5da8dSAndroid Build Coastguard Worker    @staticmethod
339*cda5da8dSAndroid Build Coastguard Worker    def _after_fork():
340*cda5da8dSAndroid Build Coastguard Worker        from . import util
341*cda5da8dSAndroid Build Coastguard Worker        util._finalizer_registry.clear()
342*cda5da8dSAndroid Build Coastguard Worker        util._run_after_forkers()
343*cda5da8dSAndroid Build Coastguard Worker
344*cda5da8dSAndroid Build Coastguard Worker
345*cda5da8dSAndroid Build Coastguard Worker#
346*cda5da8dSAndroid Build Coastguard Worker# We subclass bytes to avoid accidental transmission of auth keys over network
347*cda5da8dSAndroid Build Coastguard Worker#
348*cda5da8dSAndroid Build Coastguard Worker
349*cda5da8dSAndroid Build Coastguard Workerclass AuthenticationString(bytes):
350*cda5da8dSAndroid Build Coastguard Worker    def __reduce__(self):
351*cda5da8dSAndroid Build Coastguard Worker        from .context import get_spawning_popen
352*cda5da8dSAndroid Build Coastguard Worker        if get_spawning_popen() is None:
353*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(
354*cda5da8dSAndroid Build Coastguard Worker                'Pickling an AuthenticationString object is '
355*cda5da8dSAndroid Build Coastguard Worker                'disallowed for security reasons'
356*cda5da8dSAndroid Build Coastguard Worker                )
357*cda5da8dSAndroid Build Coastguard Worker        return AuthenticationString, (bytes(self),)
358*cda5da8dSAndroid Build Coastguard Worker
359*cda5da8dSAndroid Build Coastguard Worker
360*cda5da8dSAndroid Build Coastguard Worker#
361*cda5da8dSAndroid Build Coastguard Worker# Create object representing the parent process
362*cda5da8dSAndroid Build Coastguard Worker#
363*cda5da8dSAndroid Build Coastguard Worker
364*cda5da8dSAndroid Build Coastguard Workerclass _ParentProcess(BaseProcess):
365*cda5da8dSAndroid Build Coastguard Worker
366*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, name, pid, sentinel):
367*cda5da8dSAndroid Build Coastguard Worker        self._identity = ()
368*cda5da8dSAndroid Build Coastguard Worker        self._name = name
369*cda5da8dSAndroid Build Coastguard Worker        self._pid = pid
370*cda5da8dSAndroid Build Coastguard Worker        self._parent_pid = None
371*cda5da8dSAndroid Build Coastguard Worker        self._popen = None
372*cda5da8dSAndroid Build Coastguard Worker        self._closed = False
373*cda5da8dSAndroid Build Coastguard Worker        self._sentinel = sentinel
374*cda5da8dSAndroid Build Coastguard Worker        self._config = {}
375*cda5da8dSAndroid Build Coastguard Worker
376*cda5da8dSAndroid Build Coastguard Worker    def is_alive(self):
377*cda5da8dSAndroid Build Coastguard Worker        from multiprocessing.connection import wait
378*cda5da8dSAndroid Build Coastguard Worker        return not wait([self._sentinel], timeout=0)
379*cda5da8dSAndroid Build Coastguard Worker
380*cda5da8dSAndroid Build Coastguard Worker    @property
381*cda5da8dSAndroid Build Coastguard Worker    def ident(self):
382*cda5da8dSAndroid Build Coastguard Worker        return self._pid
383*cda5da8dSAndroid Build Coastguard Worker
384*cda5da8dSAndroid Build Coastguard Worker    def join(self, timeout=None):
385*cda5da8dSAndroid Build Coastguard Worker        '''
386*cda5da8dSAndroid Build Coastguard Worker        Wait until parent process terminates
387*cda5da8dSAndroid Build Coastguard Worker        '''
388*cda5da8dSAndroid Build Coastguard Worker        from multiprocessing.connection import wait
389*cda5da8dSAndroid Build Coastguard Worker        wait([self._sentinel], timeout=timeout)
390*cda5da8dSAndroid Build Coastguard Worker
391*cda5da8dSAndroid Build Coastguard Worker    pid = ident
392*cda5da8dSAndroid Build Coastguard Worker
393*cda5da8dSAndroid Build Coastguard Worker#
394*cda5da8dSAndroid Build Coastguard Worker# Create object representing the main process
395*cda5da8dSAndroid Build Coastguard Worker#
396*cda5da8dSAndroid Build Coastguard Worker
397*cda5da8dSAndroid Build Coastguard Workerclass _MainProcess(BaseProcess):
398*cda5da8dSAndroid Build Coastguard Worker
399*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
400*cda5da8dSAndroid Build Coastguard Worker        self._identity = ()
401*cda5da8dSAndroid Build Coastguard Worker        self._name = 'MainProcess'
402*cda5da8dSAndroid Build Coastguard Worker        self._parent_pid = None
403*cda5da8dSAndroid Build Coastguard Worker        self._popen = None
404*cda5da8dSAndroid Build Coastguard Worker        self._closed = False
405*cda5da8dSAndroid Build Coastguard Worker        self._config = {'authkey': AuthenticationString(os.urandom(32)),
406*cda5da8dSAndroid Build Coastguard Worker                        'semprefix': '/mp'}
407*cda5da8dSAndroid Build Coastguard Worker        # Note that some versions of FreeBSD only allow named
408*cda5da8dSAndroid Build Coastguard Worker        # semaphores to have names of up to 14 characters.  Therefore
409*cda5da8dSAndroid Build Coastguard Worker        # we choose a short prefix.
410*cda5da8dSAndroid Build Coastguard Worker        #
411*cda5da8dSAndroid Build Coastguard Worker        # On MacOSX in a sandbox it may be necessary to use a
412*cda5da8dSAndroid Build Coastguard Worker        # different prefix -- see #19478.
413*cda5da8dSAndroid Build Coastguard Worker        #
414*cda5da8dSAndroid Build Coastguard Worker        # Everything in self._config will be inherited by descendant
415*cda5da8dSAndroid Build Coastguard Worker        # processes.
416*cda5da8dSAndroid Build Coastguard Worker
417*cda5da8dSAndroid Build Coastguard Worker    def close(self):
418*cda5da8dSAndroid Build Coastguard Worker        pass
419*cda5da8dSAndroid Build Coastguard Worker
420*cda5da8dSAndroid Build Coastguard Worker
421*cda5da8dSAndroid Build Coastguard Worker_parent_process = None
422*cda5da8dSAndroid Build Coastguard Worker_current_process = _MainProcess()
423*cda5da8dSAndroid Build Coastguard Worker_process_counter = itertools.count(1)
424*cda5da8dSAndroid Build Coastguard Worker_children = set()
425*cda5da8dSAndroid Build Coastguard Workerdel _MainProcess
426*cda5da8dSAndroid Build Coastguard Worker
427*cda5da8dSAndroid Build Coastguard Worker#
428*cda5da8dSAndroid Build Coastguard Worker# Give names to some return codes
429*cda5da8dSAndroid Build Coastguard Worker#
430*cda5da8dSAndroid Build Coastguard Worker
431*cda5da8dSAndroid Build Coastguard Worker_exitcode_to_name = {}
432*cda5da8dSAndroid Build Coastguard Worker
433*cda5da8dSAndroid Build Coastguard Workerfor name, signum in list(signal.__dict__.items()):
434*cda5da8dSAndroid Build Coastguard Worker    if name[:3]=='SIG' and '_' not in name:
435*cda5da8dSAndroid Build Coastguard Worker        _exitcode_to_name[-signum] = f'-{name}'
436*cda5da8dSAndroid Build Coastguard Workerdel name, signum
437*cda5da8dSAndroid Build Coastguard Worker
438*cda5da8dSAndroid Build Coastguard Worker# For debug and leak testing
439*cda5da8dSAndroid Build Coastguard Worker_dangling = WeakSet()
440