10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Module providing the `Process` class which emulates `threading.Thread`
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# multiprocessing/process.py
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Copyright (c) 2006-2008, R Oudkerk
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# All rights reserved.
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Redistribution and use in source and binary forms, with or without
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# modification, are permitted provided that the following conditions
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# are met:
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 1. Redistributions of source code must retain the above copyright
140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#    notice, this list of conditions and the following disclaimer.
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 2. Redistributions in binary form must reproduce the above copyright
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#    notice, this list of conditions and the following disclaimer in the
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#    documentation and/or other materials provided with the distribution.
180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 3. Neither the name of author nor the names of any contributors may be
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#    used to endorse or promote products derived from this software
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#    without specific prior written permission.
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# SUCH DAMAGE.
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__all__ = ['Process', 'current_process', 'active_children']
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Imports
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport signal
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport itertools
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gaotry:
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ORIGINAL_DIR = os.path.abspath(os.getcwd())
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexcept OSError:
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ORIGINAL_DIR = None
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Public functions
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef current_process():
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Return process object representing the current process
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return _current_process
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef active_children():
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Return list of process objects corresponding to live child processes
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _cleanup()
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return list(_current_process._children)
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _cleanup():
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # check for processes which have finished
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for p in list(_current_process._children):
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if p._popen.poll() is not None:
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            _current_process._children.discard(p)
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# The `Process` class
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass Process(object):
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Process objects represent activity that is run in a separate process
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    The class is analagous to `threading.Thread`
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _Popen = None
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert group is None, 'group argument must be None for now'
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        count = _current_process._counter.next()
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._identity = _current_process._identity + (count,)
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._authkey = _current_process._authkey
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._daemonic = _current_process._daemonic
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._tempdir = _current_process._tempdir
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._parent_pid = os.getpid()
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._popen = None
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._target = target
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._args = tuple(args)
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._kwargs = dict(kwargs)
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._name = name or type(self).__name__ + '-' + \
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                     ':'.join(str(i) for i in self._identity)
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def run(self):
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Method to be run in sub-process; can be overridden in sub-class
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self._target:
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self._target(*self._args, **self._kwargs)
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def start(self):
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Start child process
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert self._popen is None, 'cannot start a process twice'
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert self._parent_pid == os.getpid(), \
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao               'can only start a process object created by current process'
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert not _current_process._daemonic, \
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao               'daemonic processes are not allowed to have children'
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _cleanup()
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self._Popen is not None:
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            Popen = self._Popen
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from .forking import Popen
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._popen = Popen(self)
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _current_process._children.add(self)
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def terminate(self):
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Terminate process; sends SIGTERM signal or uses TerminateProcess()
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._popen.terminate()
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def join(self, timeout=None):
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Wait until child process terminates
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert self._parent_pid == os.getpid(), 'can only join a child process'
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert self._popen is not None, 'can only join a started process'
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        res = self._popen.wait(timeout)
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if res is not None:
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            _current_process._children.discard(self)
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def is_alive(self):
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Return whether process is alive
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self is _current_process:
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return True
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert self._parent_pid == os.getpid(), 'can only test a child process'
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self._popen is None:
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return False
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._popen.poll()
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self._popen.returncode is None
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @property
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def name(self):
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self._name
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @name.setter
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def name(self, name):
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert isinstance(name, basestring), 'name must be a string'
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._name = name
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @property
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def daemon(self):
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Return whether process is a daemon
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self._daemonic
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @daemon.setter
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def daemon(self, daemonic):
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Set whether process is a daemon
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert self._popen is None, 'process has already started'
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._daemonic = daemonic
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @property
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def authkey(self):
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self._authkey
1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @authkey.setter
1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def authkey(self, authkey):
1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Set authorization key of process
1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._authkey = AuthenticationString(authkey)
1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @property
1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def exitcode(self):
1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Return exit code of process or `None` if it has yet to stop
2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self._popen is None:
2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return self._popen
2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self._popen.poll()
2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @property
2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def ident(self):
2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Return identifier (PID) of process or `None` if it has yet to start
2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self is _current_process:
2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return os.getpid()
2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return self._popen and self._popen.pid
2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    pid = ident
2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __repr__(self):
2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self is _current_process:
2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            status = 'started'
2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif self._parent_pid != os.getpid():
2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            status = 'unknown'
2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif self._popen is None:
2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            status = 'initial'
2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self._popen.poll() is not None:
2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                status = self.exitcode
2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                status = 'started'
2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if type(status) is int:
2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if status == 0:
2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                status = 'stopped'
2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                status = 'stopped[%s]' % _exitcode_to_name.get(status, status)
2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return '<%s(%s, %s%s)>' % (type(self).__name__, self._name,
2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                   status, self._daemonic and ' daemon' or '')
2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ##
2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def _bootstrap(self):
2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from . import util
2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        global _current_process
2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self._children = set()
2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self._counter = itertools.count(1)
2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                sys.stdin.close()
2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                sys.stdin = open(os.devnull)
2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            except (OSError, ValueError):
2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                pass
2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            _current_process = self
2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            util._finalizer_registry.clear()
2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            util._run_after_forkers()
2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            util.info('child process calling self.run()')
2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.run()
2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                exitcode = 0
2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            finally:
2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                util._exit_function()
2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except SystemExit, e:
2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if not e.args:
2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                exitcode = 1
2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            elif isinstance(e.args[0], int):
2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                exitcode = e.args[0]
2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                sys.stderr.write(str(e.args[0]) + '\n')
2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                sys.stderr.flush()
2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                exitcode = 0 if isinstance(e.args[0], str) else 1
2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except:
2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            exitcode = 1
2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            import traceback
2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.stderr.write('Process %s:\n' % self.name)
2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.stderr.flush()
2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            traceback.print_exc()
2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        util.info('process exiting with exitcode %d' % exitcode)
2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return exitcode
2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# We subclass bytes to avoid accidental transmission of auth keys over network
2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass AuthenticationString(bytes):
2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __reduce__(self):
2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from .forking import Popen
2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not Popen.thread_is_spawning():
2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise TypeError(
2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                'Pickling an AuthenticationString object is '
2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                'disallowed for security reasons'
2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                )
2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return AuthenticationString, (bytes(self),)
2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Create object representing the main process
2970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass _MainProcess(Process):
3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self):
3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._identity = ()
3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._daemonic = False
3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._name = 'MainProcess'
3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._parent_pid = None
3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._popen = None
3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._counter = itertools.count(1)
3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._children = set()
3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._authkey = AuthenticationString(os.urandom(32))
3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._tempdir = None
3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao_current_process = _MainProcess()
3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodel _MainProcess
3140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Give names to some return codes
3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
3180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao_exitcode_to_name = {}
3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofor name, signum in signal.__dict__.items():
3220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if name[:3]=='SIG' and '_' not in name:
3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _exitcode_to_name[-signum] = name
324