10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Module for starting a process object using os.fork() or CreateProcess()
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# multiprocessing/forking.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 Gaoimport os
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport signal
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport errno
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom multiprocessing import util, process
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__all__ = ['Popen', 'assert_spawning', 'exit', 'duplicate', 'close', 'ForkingPickler']
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Check that the current thread is spawning a child process
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef assert_spawning(self):
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if not Popen.thread_is_spawning():
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        raise RuntimeError(
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            '%s objects should only be shared between processes'
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ' through inheritance' % type(self).__name__
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            )
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Try making some callable types picklable
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom pickle import Pickler
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass ForkingPickler(Pickler):
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    dispatch = Pickler.dispatch.copy()
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    @classmethod
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def register(cls, type, reduce):
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def dispatcher(self, obj):
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            rv = reduce(obj)
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.save_reduce(obj=obj, *rv)
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cls.dispatch[type] = dispatcher
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _reduce_method(m):
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if m.im_self is None:
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return getattr, (m.im_class, m.im_func.func_name)
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return getattr, (m.im_self, m.im_func.func_name)
750a8c90248264a8b26970b4473770bcc3df8515fJosh GaoForkingPickler.register(type(ForkingPickler.save), _reduce_method)
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _reduce_method_descriptor(m):
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return getattr, (m.__objclass__, m.__name__)
790a8c90248264a8b26970b4473770bcc3df8515fJosh GaoForkingPickler.register(type(list.append), _reduce_method_descriptor)
800a8c90248264a8b26970b4473770bcc3df8515fJosh GaoForkingPickler.register(type(int.__add__), _reduce_method_descriptor)
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#def _reduce_builtin_function_or_method(m):
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#    return getattr, (m.__self__, m.__name__)
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#ForkingPickler.register(type(list().append), _reduce_builtin_function_or_method)
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#ForkingPickler.register(type(int().__add__), _reduce_builtin_function_or_method)
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gaotry:
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from functools import partial
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexcept ImportError:
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    pass
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoelse:
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def _reduce_partial(p):
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return _rebuild_partial, (p.func, p.args, p.keywords or {})
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def _rebuild_partial(func, args, keywords):
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return partial(func, *args, **keywords)
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ForkingPickler.register(partial, _reduce_partial)
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Unix
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif sys.platform != 'win32':
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import time
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    exit = os._exit
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    duplicate = os.dup
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    close = os.close
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # We define a Popen class similar to the one from subprocess, but
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # whose constructor takes a process object as its argument.
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    class Popen(object):
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def __init__(self, process_obj):
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.stdout.flush()
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.stderr.flush()
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.returncode = None
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.pid = os.fork()
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self.pid == 0:
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if 'random' in sys.modules:
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    import random
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    random.seed()
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                code = process_obj._bootstrap()
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                sys.stdout.flush()
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                sys.stderr.flush()
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                os._exit(code)
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def poll(self, flag=os.WNOHANG):
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self.returncode is None:
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                while True:
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    try:
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        pid, sts = os.waitpid(self.pid, flag)
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    except os.error as e:
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        if e.errno == errno.EINTR:
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            continue
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        # Child process not yet created. See #1731717
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        # e.errno == errno.ECHILD == 10
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        return None
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    else:
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        break
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if pid == self.pid:
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if os.WIFSIGNALED(sts):
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.returncode = -os.WTERMSIG(sts)
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    else:
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        assert os.WIFEXITED(sts)
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.returncode = os.WEXITSTATUS(sts)
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return self.returncode
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def wait(self, timeout=None):
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if timeout is None:
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return self.poll(0)
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            deadline = time.time() + timeout
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            delay = 0.0005
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            while 1:
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                res = self.poll()
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if res is not None:
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                remaining = deadline - time.time()
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if remaining <= 0:
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                delay = min(delay * 2, remaining, 0.05)
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                time.sleep(delay)
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return res
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def terminate(self):
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self.returncode is None:
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                try:
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    os.kill(self.pid, signal.SIGTERM)
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                except OSError, e:
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if self.wait(timeout=0.1) is None:
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        raise
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        @staticmethod
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def thread_is_spawning():
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return False
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Windows
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoelse:
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import thread
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import msvcrt
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import _subprocess
1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import time
1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from _multiprocessing import win32, Connection, PipeConnection
1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from .util import Finalize
1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #try:
1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #    from cPickle import dump, load, HIGHEST_PROTOCOL
1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #except ImportError:
1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from pickle import load, HIGHEST_PROTOCOL
1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def dump(obj, file, protocol=None):
1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        ForkingPickler(file, protocol).dump(obj)
2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    TERMINATE = 0x10000
2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    exit = win32.ExitProcess
2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    close = win32.CloseHandle
2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # _python_exe is the assumed path to the python executable.
2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # People embedding Python want to modify it.
2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if WINSERVICE:
2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _python_exe = os.path.join(sys.exec_prefix, 'python.exe')
2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _python_exe = sys.executable
2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def set_executable(exe):
2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        global _python_exe
2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _python_exe = exe
2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def duplicate(handle, target_process=None, inheritable=False):
2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if target_process is None:
2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            target_process = _subprocess.GetCurrentProcess()
2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return _subprocess.DuplicateHandle(
2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            _subprocess.GetCurrentProcess(), handle, target_process,
2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            0, inheritable, _subprocess.DUPLICATE_SAME_ACCESS
2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ).Detach()
2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # We define a Popen class similar to the one from subprocess, but
2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # whose constructor takes a process object as its argument.
2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    class Popen(object):
2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Start a subprocess to run the code of a process object
2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _tls = thread._local()
2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def __init__(self, process_obj):
2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # create pipe for communication with child
2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            rfd, wfd = os.pipe()
2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # get handle for read end of the pipe and make it inheritable
2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            rhandle = duplicate(msvcrt.get_osfhandle(rfd), inheritable=True)
2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            os.close(rfd)
2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # start process
2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cmd = get_command_line() + [rhandle]
2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cmd = ' '.join('"%s"' % x for x in cmd)
2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            hp, ht, pid, tid = _subprocess.CreateProcess(
2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                _python_exe, cmd, None, None, 1, 0, None, None, None
2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                )
2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ht.Close()
2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            close(rhandle)
2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # set attributes of self
2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.pid = pid
2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.returncode = None
2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self._handle = hp
2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # send information to child
2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            prep_data = get_preparation_data(process_obj._name)
2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            to_child = os.fdopen(wfd, 'wb')
2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            Popen._tls.process_handle = int(hp)
2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                dump(prep_data, to_child, HIGHEST_PROTOCOL)
2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                dump(process_obj, to_child, HIGHEST_PROTOCOL)
2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            finally:
2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                del Popen._tls.process_handle
2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                to_child.close()
2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        @staticmethod
2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def thread_is_spawning():
2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return getattr(Popen._tls, 'process_handle', None) is not None
2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        @staticmethod
2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def duplicate_for_child(handle):
2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return duplicate(handle, Popen._tls.process_handle)
2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def wait(self, timeout=None):
2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self.returncode is None:
2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if timeout is None:
2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    msecs = _subprocess.INFINITE
2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                else:
2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    msecs = max(0, int(timeout * 1000 + 0.5))
2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if res == _subprocess.WAIT_OBJECT_0:
2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    code = _subprocess.GetExitCodeProcess(self._handle)
3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if code == TERMINATE:
3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        code = -signal.SIGTERM
3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.returncode = code
3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return self.returncode
3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def poll(self):
3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return self.wait(timeout=0)
3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def terminate(self):
3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self.returncode is None:
3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                try:
3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    _subprocess.TerminateProcess(int(self._handle), TERMINATE)
3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                except WindowsError:
3140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if self.wait(timeout=0.1) is None:
3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        raise
3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
3180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def is_forking(argv):
3220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Return whether commandline indicates we are forking
3240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if len(argv) >= 2 and argv[1] == '--multiprocessing-fork':
3260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            assert len(argv) == 3
3270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return True
3280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
3290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return False
3300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def freeze_support():
3330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Run code for process object if this in not the main process
3350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if is_forking(sys.argv):
3370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            main()
3380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.exit()
3390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def get_command_line():
3420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Returns prefix of command line used for spawning a child process
3440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if getattr(process.current_process(), '_inheriting', False):
3460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise RuntimeError('''
3470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            Attempt to start a new process before the current process
3480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            has finished its bootstrapping phase.
3490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            This probably means that you are on Windows and you have
3510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            forgotten to use the proper idiom in the main module:
3520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if __name__ == '__main__':
3540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    freeze_support()
3550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    ...
3560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            The "freeze_support()" line can be omitted if the program
3580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            is not going to be frozen to produce a Windows executable.''')
3590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if getattr(sys, 'frozen', False):
3610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return [sys.executable, '--multiprocessing-fork']
3620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
3630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            prog = 'from multiprocessing.forking import main; main()'
3640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            opts = util._args_from_interpreter_flags()
3650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return [_python_exe] + opts + ['-c', prog, '--multiprocessing-fork']
3660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def main():
3690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Run code specifed by data received over pipe
3710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        assert is_forking(sys.argv)
3730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        handle = int(sys.argv[-1])
3750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fd = msvcrt.open_osfhandle(handle, os.O_RDONLY)
3760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from_parent = os.fdopen(fd, 'rb')
3770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        process.current_process()._inheriting = True
3790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        preparation_data = load(from_parent)
3800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        prepare(preparation_data)
3810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self = load(from_parent)
3820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        process.current_process()._inheriting = False
3830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from_parent.close()
3850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        exitcode = self._bootstrap()
3870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        exit(exitcode)
3880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def get_preparation_data(name):
3910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Return info about parent needed by child to unpickle process object
3930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        '''
3940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from .util import _logger, _log_to_stderr
3950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        d = dict(
3970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            name=name,
3980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys_path=sys.path,
3990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys_argv=sys.argv,
4000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            log_to_stderr=_log_to_stderr,
4010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            orig_dir=process.ORIGINAL_DIR,
4020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            authkey=process.current_process().authkey,
4030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            )
4040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if _logger is not None:
4060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            d['log_level'] = _logger.getEffectiveLevel()
4070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not WINEXE and not WINSERVICE:
4090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            main_path = getattr(sys.modules['__main__'], '__file__', None)
4100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if not main_path and sys.argv[0] not in ('', '-c'):
4110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                main_path = sys.argv[0]
4120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if main_path is not None:
4130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if not os.path.isabs(main_path) and \
4140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                          process.ORIGINAL_DIR is not None:
4150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    main_path = os.path.join(process.ORIGINAL_DIR, main_path)
4160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                d['main_path'] = os.path.normpath(main_path)
4170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return d
4190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
4210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # Make (Pipe)Connection picklable
4220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
4230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def reduce_connection(conn):
4250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not Popen.thread_is_spawning():
4260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise RuntimeError(
4270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                'By default %s objects can only be shared between processes\n'
4280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                'using inheritance' % type(conn).__name__
4290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                )
4300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return type(conn), (Popen.duplicate_for_child(conn.fileno()),
4310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            conn.readable, conn.writable)
4320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ForkingPickler.register(Connection, reduce_connection)
4340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ForkingPickler.register(PipeConnection, reduce_connection)
4350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
4370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Prepare current process
4380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
4390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4400a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoold_main_modules = []
4410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4420a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef prepare(data):
4430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
4440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Try to get current process ready to unpickle process object
4450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''
4460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    old_main_modules.append(sys.modules['__main__'])
4470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'name' in data:
4490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        process.current_process().name = data['name']
4500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'authkey' in data:
4520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        process.current_process()._authkey = data['authkey']
4530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'log_to_stderr' in data and data['log_to_stderr']:
4550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        util.log_to_stderr()
4560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'log_level' in data:
4580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        util.get_logger().setLevel(data['log_level'])
4590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'sys_path' in data:
4610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        sys.path = data['sys_path']
4620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'sys_argv' in data:
4640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        sys.argv = data['sys_argv']
4650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'dir' in data:
4670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        os.chdir(data['dir'])
4680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'orig_dir' in data:
4700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        process.ORIGINAL_DIR = data['orig_dir']
4710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'main_path' in data:
4730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        main_path = data['main_path']
4740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        main_name = os.path.splitext(os.path.basename(main_path))[0]
4750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if main_name == '__init__':
4760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            main_name = os.path.basename(os.path.dirname(main_path))
4770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if main_name != 'ipython':
4790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            import imp
4800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if main_path is None:
4820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                dirs = None
4830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            elif os.path.basename(main_path).startswith('__init__.py'):
4840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                dirs = [os.path.dirname(os.path.dirname(main_path))]
4850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
4860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                dirs = [os.path.dirname(main_path)]
4870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            assert main_name not in sys.modules, main_name
4890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            file, path_name, etc = imp.find_module(main_name, dirs)
4900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
4910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                # We would like to do "imp.load_module('__main__', ...)"
4920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                # here.  However, that would cause 'if __name__ ==
4930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                # "__main__"' clauses to be executed.
4940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                main_module = imp.load_module(
4950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    '__parents_main__', file, path_name, etc
4960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    )
4970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            finally:
4980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if file:
4990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    file.close()
5000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.modules['__main__'] = main_module
5020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            main_module.__name__ = '__main__'
5030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # Try to make the potentially picklable objects in
5050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # sys.modules['__main__'] realize they are in the main
5060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # module -- somewhat ugly.
5070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            for obj in main_module.__dict__.values():
5080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                try:
5090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if obj.__module__ == '__parents_main__':
5100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        obj.__module__ = '__main__'
5110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                except Exception:
5120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    pass
513