14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Module providing the `Process` class which emulates `threading.Thread`
34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# multiprocessing/process.py
54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Copyright (c) 2006-2008, R Oudkerk
74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# All rights reserved.
84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Redistribution and use in source and binary forms, with or without
104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# modification, are permitted provided that the following conditions
114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# are met:
124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 1. Redistributions of source code must retain the above copyright
144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#    notice, this list of conditions and the following disclaimer.
154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 2. Redistributions in binary form must reproduce the above copyright
164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#    notice, this list of conditions and the following disclaimer in the
174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#    documentation and/or other materials provided with the distribution.
184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 3. Neither the name of author nor the names of any contributors may be
194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#    used to endorse or promote products derived from this software
204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#    without specific prior written permission.
214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# SUCH DAMAGE.
334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao__all__ = ['Process', 'current_process', 'active_children']
364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Imports
394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport os
424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport sys
434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport signal
444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport itertools
454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry:
514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ORIGINAL_DIR = os.path.abspath(os.getcwd())
524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept OSError:
534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ORIGINAL_DIR = None
544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Public functions
574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef current_process():
604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    '''
614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    Return process object representing the current process
624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    '''
634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    return _current_process
644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef active_children():
664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    '''
674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    Return list of process objects corresponding to live child processes
684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    '''
694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _cleanup()
704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    return list(_current_process._children)
714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef _cleanup():
774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # check for processes which have finished
784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    for p in list(_current_process._children):
794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if p._popen.poll() is not None:
804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            _current_process._children.discard(p)
814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# The `Process` class
844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Process(object):
874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    '''
884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    Process objects represent activity that is run in a separate process
894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    The class is analagous to `threading.Thread`
914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    '''
924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    _Popen = None
934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert group is None, 'group argument must be None for now'
964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        count = _current_process._counter.next()
974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._identity = _current_process._identity + (count,)
984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._authkey = _current_process._authkey
994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._daemonic = _current_process._daemonic
1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._tempdir = _current_process._tempdir
1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._parent_pid = os.getpid()
1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._popen = None
1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._target = target
1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._args = tuple(args)
1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._kwargs = dict(kwargs)
1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._name = name or type(self).__name__ + '-' + \
1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                     ':'.join(str(i) for i in self._identity)
1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def run(self):
1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Method to be run in sub-process; can be overridden in sub-class
1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if self._target:
1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self._target(*self._args, **self._kwargs)
1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def start(self):
1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Start child process
1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert self._popen is None, 'cannot start a process twice'
1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert self._parent_pid == os.getpid(), \
1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao               'can only start a process object created by current process'
1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert not _current_process._daemonic, \
1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao               'daemonic processes are not allowed to have children'
1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        _cleanup()
1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if self._Popen is not None:
1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            Popen = self._Popen
1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        else:
1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            from .forking import Popen
1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._popen = Popen(self)
1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        _current_process._children.add(self)
1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def terminate(self):
1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Terminate process; sends SIGTERM signal or uses TerminateProcess()
1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._popen.terminate()
1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def join(self, timeout=None):
1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Wait until child process terminates
1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert self._parent_pid == os.getpid(), 'can only join a child process'
1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert self._popen is not None, 'can only join a started process'
1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        res = self._popen.wait(timeout)
1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if res is not None:
1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            _current_process._children.discard(self)
1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def is_alive(self):
1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Return whether process is alive
1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if self is _current_process:
1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return True
1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert self._parent_pid == os.getpid(), 'can only test a child process'
1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if self._popen is None:
1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return False
1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._popen.poll()
1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return self._popen.returncode is None
1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @property
1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def name(self):
1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return self._name
1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @name.setter
1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def name(self, name):
1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert isinstance(name, basestring), 'name must be a string'
1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._name = name
1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @property
1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def daemon(self):
1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Return whether process is a daemon
1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return self._daemonic
1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @daemon.setter
1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def daemon(self, daemonic):
1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Set whether process is a daemon
1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        assert self._popen is None, 'process has already started'
1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._daemonic = daemonic
1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @property
1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def authkey(self):
1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return self._authkey
1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @authkey.setter
1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def authkey(self, authkey):
1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Set authorization key of process
1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._authkey = AuthenticationString(authkey)
1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @property
1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def exitcode(self):
1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Return exit code of process or `None` if it has yet to stop
2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if self._popen is None:
2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return self._popen
2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return self._popen.poll()
2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @property
2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def ident(self):
2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        Return identifier (PID) of process or `None` if it has yet to start
2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''
2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if self is _current_process:
2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return os.getpid()
2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        else:
2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return self._popen and self._popen.pid
2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    pid = ident
2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def __repr__(self):
2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if self is _current_process:
2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            status = 'started'
2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        elif self._parent_pid != os.getpid():
2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            status = 'unknown'
2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        elif self._popen is None:
2234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            status = 'initial'
2244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        else:
2254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if self._popen.poll() is not None:
2264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                status = self.exitcode
2274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            else:
2284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                status = 'started'
2294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if type(status) is int:
2314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if status == 0:
2324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                status = 'stopped'
2334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            else:
2344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                status = 'stopped[%s]' % _exitcode_to_name.get(status, status)
2354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return '<%s(%s, %s%s)>' % (type(self).__name__, self._name,
2374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                   status, self._daemonic and ' daemon' or '')
2384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    ##
2404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def _bootstrap(self):
2424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        from . import util
2434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        global _current_process
2444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
2464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self._children = set()
2474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self._counter = itertools.count(1)
2484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            try:
2494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                sys.stdin.close()
2504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                sys.stdin = open(os.devnull)
2514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            except (OSError, ValueError):
2524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                pass
2534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            _current_process = self
2544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            util._finalizer_registry.clear()
2554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            util._run_after_forkers()
2564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            util.info('child process calling self.run()')
2574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            try:
2584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.run()
2594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                exitcode = 0
2604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            finally:
2614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                util._exit_function()
2624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except SystemExit, e:
2634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not e.args:
2644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                exitcode = 1
2654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            elif isinstance(e.args[0], int):
2664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                exitcode = e.args[0]
2674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            else:
2684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                sys.stderr.write(str(e.args[0]) + '\n')
2694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                sys.stderr.flush()
2704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                exitcode = 0 if isinstance(e.args[0], str) else 1
2714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except:
2724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            exitcode = 1
2734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            import traceback
2744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            sys.stderr.write('Process %s:\n' % self.name)
2754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            sys.stderr.flush()
2764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            traceback.print_exc()
2774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        util.info('process exiting with exitcode %d' % exitcode)
2794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return exitcode
2804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
2824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# We subclass bytes to avoid accidental transmission of auth keys over network
2834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
2844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass AuthenticationString(bytes):
2864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def __reduce__(self):
2874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        from .forking import Popen
2884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if not Popen.thread_is_spawning():
2894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            raise TypeError(
2904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                'Pickling an AuthenticationString object is '
2914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                'disallowed for security reasons'
2924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                )
2934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return AuthenticationString, (bytes(self),)
2944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
2964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Create object representing the main process
2974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
2984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass _MainProcess(Process):
3004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def __init__(self):
3024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._identity = ()
3034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._daemonic = False
3044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._name = 'MainProcess'
3054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._parent_pid = None
3064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._popen = None
3074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._counter = itertools.count(1)
3084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._children = set()
3094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._authkey = AuthenticationString(os.urandom(32))
3104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self._tempdir = None
3114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao_current_process = _MainProcess()
3134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodel _MainProcess
3144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
3164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Give names to some return codes
3174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#
3184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao_exitcode_to_name = {}
3204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofor name, signum in signal.__dict__.items():
3224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    if name[:3]=='SIG' and '_' not in name:
3234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        _exitcode_to_name[-signum] = name
324