| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # Module for starting a process object using os.fork() or CreateProcess() | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # multiprocessing/forking.py | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2010-12-14 01:38:16 +00:00
										 |  |  | # Copyright (c) 2006-2008, R Oudkerk | 
					
						
							| 
									
										
										
										
											2012-04-30 12:13:55 +01:00
										 |  |  | # Licensed to PSF under a Contributor Agreement. | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import signal | 
					
						
							| 
									
										
										
										
											2013-02-26 12:39:57 +00:00
										 |  |  | import errno | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | from multiprocessing import util, process | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-14 15:30:10 +01:00
										 |  |  | __all__ = ['Popen', 'assert_spawning', 'duplicate', 'close', 'ForkingPickler'] | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Check that the current thread is spawning a child process | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def assert_spawning(self): | 
					
						
							|  |  |  |     if not Popen.thread_is_spawning(): | 
					
						
							|  |  |  |         raise RuntimeError( | 
					
						
							|  |  |  |             '%s objects should only be shared between processes' | 
					
						
							|  |  |  |             ' through inheritance' % type(self).__name__ | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 21:30:55 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # Try making some callable types picklable | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-17 00:23:04 +01:00
										 |  |  | from pickle import Pickler | 
					
						
							|  |  |  | from copyreg import dispatch_table | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 21:30:55 +00:00
										 |  |  | class ForkingPickler(Pickler): | 
					
						
							| 
									
										
										
										
											2012-03-17 00:23:04 +01:00
										 |  |  |     _extra_reducers = {} | 
					
						
							|  |  |  |     def __init__(self, *args): | 
					
						
							|  |  |  |         Pickler.__init__(self, *args) | 
					
						
							|  |  |  |         self.dispatch_table = dispatch_table.copy() | 
					
						
							|  |  |  |         self.dispatch_table.update(self._extra_reducers) | 
					
						
							| 
									
										
										
										
											2008-08-19 21:30:55 +00:00
										 |  |  |     @classmethod | 
					
						
							|  |  |  |     def register(cls, type, reduce): | 
					
						
							| 
									
										
										
										
											2012-03-17 00:23:04 +01:00
										 |  |  |         cls._extra_reducers[type] = reduce | 
					
						
							| 
									
										
										
										
											2008-08-19 21:30:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def _reduce_method(m): | 
					
						
							|  |  |  |     if m.__self__ is None: | 
					
						
							|  |  |  |         return getattr, (m.__class__, m.__func__.__name__) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return getattr, (m.__self__, m.__func__.__name__) | 
					
						
							|  |  |  | class _C: | 
					
						
							|  |  |  |     def f(self): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | ForkingPickler.register(type(_C().f), _reduce_method) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _reduce_method_descriptor(m): | 
					
						
							|  |  |  |     return getattr, (m.__objclass__, m.__name__) | 
					
						
							|  |  |  | ForkingPickler.register(type(list.append), _reduce_method_descriptor) | 
					
						
							|  |  |  | ForkingPickler.register(type(int.__add__), _reduce_method_descriptor) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     from functools import partial | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     def _reduce_partial(p): | 
					
						
							|  |  |  |         return _rebuild_partial, (p.func, p.args, p.keywords or {}) | 
					
						
							|  |  |  |     def _rebuild_partial(func, args, keywords): | 
					
						
							|  |  |  |         return partial(func, *args, **keywords) | 
					
						
							|  |  |  |     ForkingPickler.register(partial, _reduce_partial) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # Unix | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if sys.platform != 'win32': | 
					
						
							|  |  |  |     duplicate = os.dup | 
					
						
							|  |  |  |     close = os.close | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # We define a Popen class similar to the one from subprocess, but | 
					
						
							|  |  |  |     # whose constructor takes a process object as its argument. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Popen(object): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __init__(self, process_obj): | 
					
						
							|  |  |  |             sys.stdout.flush() | 
					
						
							|  |  |  |             sys.stderr.flush() | 
					
						
							|  |  |  |             self.returncode = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-06 19:35:31 +02:00
										 |  |  |             r, w = os.pipe() | 
					
						
							|  |  |  |             self.sentinel = r | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |             self.pid = os.fork() | 
					
						
							|  |  |  |             if self.pid == 0: | 
					
						
							| 
									
										
										
										
											2011-06-06 19:35:31 +02:00
										 |  |  |                 os.close(r) | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                 if 'random' in sys.modules: | 
					
						
							|  |  |  |                     import random | 
					
						
							|  |  |  |                     random.seed() | 
					
						
							|  |  |  |                 code = process_obj._bootstrap() | 
					
						
							|  |  |  |                 os._exit(code) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-06 19:35:31 +02:00
										 |  |  |             # `w` will be closed when the child exits, at which point `r` | 
					
						
							|  |  |  |             # will become ready for reading (using e.g. select()). | 
					
						
							|  |  |  |             os.close(w) | 
					
						
							|  |  |  |             util.Finalize(self, os.close, (r,)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |         def poll(self, flag=os.WNOHANG): | 
					
						
							|  |  |  |             if self.returncode is None: | 
					
						
							| 
									
										
										
										
											2013-02-26 12:39:57 +00:00
										 |  |  |                 while True: | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         pid, sts = os.waitpid(self.pid, flag) | 
					
						
							| 
									
										
										
										
											2013-02-26 13:11:11 +00:00
										 |  |  |                     except OSError as e: | 
					
						
							| 
									
										
										
										
											2013-02-26 12:39:57 +00:00
										 |  |  |                         if e.errno == errno.EINTR: | 
					
						
							|  |  |  |                             continue | 
					
						
							|  |  |  |                         # Child process not yet created. See #1731717 | 
					
						
							|  |  |  |                         # e.errno == errno.ECHILD == 10 | 
					
						
							|  |  |  |                         return None | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         break | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                 if pid == self.pid: | 
					
						
							|  |  |  |                     if os.WIFSIGNALED(sts): | 
					
						
							|  |  |  |                         self.returncode = -os.WTERMSIG(sts) | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         assert os.WIFEXITED(sts) | 
					
						
							|  |  |  |                         self.returncode = os.WEXITSTATUS(sts) | 
					
						
							|  |  |  |             return self.returncode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def wait(self, timeout=None): | 
					
						
							| 
									
										
										
										
											2011-06-06 19:35:31 +02:00
										 |  |  |             if self.returncode is None: | 
					
						
							|  |  |  |                 if timeout is not None: | 
					
						
							| 
									
										
										
										
											2012-05-10 16:11:12 +01:00
										 |  |  |                     from .connection import wait | 
					
						
							|  |  |  |                     if not wait([self.sentinel], timeout): | 
					
						
							| 
									
										
										
										
											2011-06-06 19:35:31 +02:00
										 |  |  |                         return None | 
					
						
							| 
									
										
										
										
											2012-05-10 16:11:12 +01:00
										 |  |  |                 # This shouldn't block if wait() returned successfully. | 
					
						
							| 
									
										
										
										
											2011-06-06 19:35:31 +02:00
										 |  |  |                 return self.poll(os.WNOHANG if timeout == 0.0 else 0) | 
					
						
							|  |  |  |             return self.returncode | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def terminate(self): | 
					
						
							|  |  |  |             if self.returncode is None: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     os.kill(self.pid, signal.SIGTERM) | 
					
						
							| 
									
										
										
										
											2011-11-11 20:05:50 +01:00
										 |  |  |                 except OSError: | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                     if self.wait(timeout=0.1) is None: | 
					
						
							|  |  |  |                         raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def thread_is_spawning(): | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Windows | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     import _thread | 
					
						
							|  |  |  |     import msvcrt | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     import _winapi | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 20:05:50 +01:00
										 |  |  |     from pickle import load, HIGHEST_PROTOCOL | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 21:30:55 +00:00
										 |  |  |     def dump(obj, file, protocol=None): | 
					
						
							|  |  |  |         ForkingPickler(file, protocol).dump(obj) | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     TERMINATE = 0x10000 | 
					
						
							|  |  |  |     WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False)) | 
					
						
							| 
									
										
										
										
											2011-04-11 17:56:23 -05:00
										 |  |  |     WINSERVICE = sys.executable.lower().endswith("pythonservice.exe") | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     close = _winapi.CloseHandle | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # _python_exe is the assumed path to the python executable. | 
					
						
							|  |  |  |     # People embedding Python want to modify it. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 17:56:23 -05:00
										 |  |  |     if WINSERVICE: | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |         _python_exe = os.path.join(sys.exec_prefix, 'python.exe') | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         _python_exe = sys.executable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_executable(exe): | 
					
						
							|  |  |  |         global _python_exe | 
					
						
							|  |  |  |         _python_exe = exe | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def duplicate(handle, target_process=None, inheritable=False): | 
					
						
							|  |  |  |         if target_process is None: | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |             target_process = _winapi.GetCurrentProcess() | 
					
						
							|  |  |  |         return _winapi.DuplicateHandle( | 
					
						
							|  |  |  |             _winapi.GetCurrentProcess(), handle, target_process, | 
					
						
							|  |  |  |             0, inheritable, _winapi.DUPLICATE_SAME_ACCESS | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # We define a Popen class similar to the one from subprocess, but | 
					
						
							|  |  |  |     # whose constructor takes a process object as its argument. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Popen(object): | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         Start a subprocess to run the code of a process object | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         _tls = _thread._local() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __init__(self, process_obj): | 
					
						
							| 
									
										
										
										
											2012-06-04 18:59:10 +01:00
										 |  |  |             cmd = ' '.join('"%s"' % x for x in get_command_line()) | 
					
						
							|  |  |  |             prep_data = get_preparation_data(process_obj._name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |             # create pipe for communication with child | 
					
						
							|  |  |  |             rfd, wfd = os.pipe() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # get handle for read end of the pipe and make it inheritable | 
					
						
							|  |  |  |             rhandle = duplicate(msvcrt.get_osfhandle(rfd), inheritable=True) | 
					
						
							|  |  |  |             os.close(rfd) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-04 18:59:10 +01:00
										 |  |  |             with open(wfd, 'wb', closefd=True) as to_child: | 
					
						
							|  |  |  |                 # start process | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     hp, ht, pid, tid = _winapi.CreateProcess( | 
					
						
							|  |  |  |                         _python_exe, cmd + (' %s' % rhandle), | 
					
						
							|  |  |  |                         None, None, 1, 0, None, None, None | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  |                     _winapi.CloseHandle(ht) | 
					
						
							|  |  |  |                 finally: | 
					
						
							|  |  |  |                     close(rhandle) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # set attributes of self | 
					
						
							|  |  |  |                 self.pid = pid | 
					
						
							|  |  |  |                 self.returncode = None | 
					
						
							|  |  |  |                 self._handle = hp | 
					
						
							|  |  |  |                 self.sentinel = int(hp) | 
					
						
							| 
									
										
										
										
											2012-11-15 18:16:35 +00:00
										 |  |  |                 util.Finalize(self, _winapi.CloseHandle, (self.sentinel,)) | 
					
						
							| 
									
										
										
										
											2012-06-04 18:59:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # send information to child | 
					
						
							|  |  |  |                 Popen._tls.process_handle = int(hp) | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     dump(prep_data, to_child, HIGHEST_PROTOCOL) | 
					
						
							|  |  |  |                     dump(process_obj, to_child, HIGHEST_PROTOCOL) | 
					
						
							|  |  |  |                 finally: | 
					
						
							|  |  |  |                     del Popen._tls.process_handle | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def thread_is_spawning(): | 
					
						
							|  |  |  |             return getattr(Popen._tls, 'process_handle', None) is not None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def duplicate_for_child(handle): | 
					
						
							|  |  |  |             return duplicate(handle, Popen._tls.process_handle) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def wait(self, timeout=None): | 
					
						
							|  |  |  |             if self.returncode is None: | 
					
						
							|  |  |  |                 if timeout is None: | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                     msecs = _winapi.INFINITE | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     msecs = max(0, int(timeout * 1000 + 0.5)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                 res = _winapi.WaitForSingleObject(int(self._handle), msecs) | 
					
						
							|  |  |  |                 if res == _winapi.WAIT_OBJECT_0: | 
					
						
							|  |  |  |                     code = _winapi.GetExitCodeProcess(self._handle) | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                     if code == TERMINATE: | 
					
						
							|  |  |  |                         code = -signal.SIGTERM | 
					
						
							|  |  |  |                     self.returncode = code | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return self.returncode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def poll(self): | 
					
						
							|  |  |  |             return self.wait(timeout=0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def terminate(self): | 
					
						
							|  |  |  |             if self.returncode is None: | 
					
						
							|  |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                     _winapi.TerminateProcess(int(self._handle), TERMINATE) | 
					
						
							| 
									
										
										
										
											2012-08-01 17:44:18 +01:00
										 |  |  |                 except OSError: | 
					
						
							|  |  |  |                     if self.wait(timeout=1.0) is None: | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                         raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def is_forking(argv): | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         Return whether commandline indicates we are forking | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         if len(argv) >= 2 and argv[1] == '--multiprocessing-fork': | 
					
						
							|  |  |  |             assert len(argv) == 3 | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def freeze_support(): | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         Run code for process object if this in not the main process | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         if is_forking(sys.argv): | 
					
						
							|  |  |  |             main() | 
					
						
							|  |  |  |             sys.exit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_command_line(): | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         Returns prefix of command line used for spawning a child process | 
					
						
							|  |  |  |         '''
 | 
					
						
							| 
									
										
										
										
											2012-08-14 11:41:32 +01:00
										 |  |  |         if getattr(process.current_process(), '_inheriting', False): | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |             raise RuntimeError('''
 | 
					
						
							|  |  |  |             Attempt to start a new process before the current process | 
					
						
							|  |  |  |             has finished its bootstrapping phase. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             This probably means that you are on Windows and you have | 
					
						
							|  |  |  |             forgotten to use the proper idiom in the main module: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if __name__ == '__main__': | 
					
						
							|  |  |  |                     freeze_support() | 
					
						
							|  |  |  |                     ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             The "freeze_support()" line can be omitted if the program | 
					
						
							|  |  |  |             is not going to be frozen to produce a Windows executable.''')
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if getattr(sys, 'frozen', False): | 
					
						
							|  |  |  |             return [sys.executable, '--multiprocessing-fork'] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             prog = 'from multiprocessing.forking import main; main()' | 
					
						
							| 
									
										
										
										
											2012-05-18 14:28:02 +01:00
										 |  |  |             opts = util._args_from_interpreter_flags() | 
					
						
							|  |  |  |             return [_python_exe] + opts + ['-c', prog, '--multiprocessing-fork'] | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def main(): | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         Run code specifed by data received over pipe | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         assert is_forking(sys.argv) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         handle = int(sys.argv[-1]) | 
					
						
							|  |  |  |         fd = msvcrt.open_osfhandle(handle, os.O_RDONLY) | 
					
						
							|  |  |  |         from_parent = os.fdopen(fd, 'rb') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         process.current_process()._inheriting = True | 
					
						
							|  |  |  |         preparation_data = load(from_parent) | 
					
						
							|  |  |  |         prepare(preparation_data) | 
					
						
							|  |  |  |         self = load(from_parent) | 
					
						
							|  |  |  |         process.current_process()._inheriting = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         from_parent.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         exitcode = self._bootstrap() | 
					
						
							| 
									
										
										
										
											2012-06-14 15:30:10 +01:00
										 |  |  |         sys.exit(exitcode) | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_preparation_data(name): | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         Return info about parent needed by child to unpickle process object | 
					
						
							|  |  |  |         '''
 | 
					
						
							|  |  |  |         from .util import _logger, _log_to_stderr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         d = dict( | 
					
						
							|  |  |  |             name=name, | 
					
						
							|  |  |  |             sys_path=sys.path, | 
					
						
							|  |  |  |             sys_argv=sys.argv, | 
					
						
							|  |  |  |             log_to_stderr=_log_to_stderr, | 
					
						
							|  |  |  |             orig_dir=process.ORIGINAL_DIR, | 
					
						
							| 
									
										
										
										
											2008-08-19 19:17:39 +00:00
										 |  |  |             authkey=process.current_process().authkey, | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if _logger is not None: | 
					
						
							|  |  |  |             d['log_level'] = _logger.getEffectiveLevel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 17:56:23 -05:00
										 |  |  |         if not WINEXE and not WINSERVICE: | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |             main_path = getattr(sys.modules['__main__'], '__file__', None) | 
					
						
							|  |  |  |             if not main_path and sys.argv[0] not in ('', '-c'): | 
					
						
							|  |  |  |                 main_path = sys.argv[0] | 
					
						
							|  |  |  |             if main_path is not None: | 
					
						
							|  |  |  |                 if not os.path.isabs(main_path) and \ | 
					
						
							|  |  |  |                                           process.ORIGINAL_DIR is not None: | 
					
						
							|  |  |  |                     main_path = os.path.join(process.ORIGINAL_DIR, main_path) | 
					
						
							|  |  |  |                 d['main_path'] = os.path.normpath(main_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return d | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Prepare current process | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | old_main_modules = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def prepare(data): | 
					
						
							|  |  |  |     '''
 | 
					
						
							|  |  |  |     Try to get current process ready to unpickle process object | 
					
						
							|  |  |  |     '''
 | 
					
						
							|  |  |  |     old_main_modules.append(sys.modules['__main__']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'name' in data: | 
					
						
							| 
									
										
										
										
											2008-08-19 19:17:39 +00:00
										 |  |  |         process.current_process().name = data['name'] | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if 'authkey' in data: | 
					
						
							|  |  |  |         process.current_process()._authkey = data['authkey'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'log_to_stderr' in data and data['log_to_stderr']: | 
					
						
							|  |  |  |         util.log_to_stderr() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'log_level' in data: | 
					
						
							|  |  |  |         util.get_logger().setLevel(data['log_level']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'sys_path' in data: | 
					
						
							|  |  |  |         sys.path = data['sys_path'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'sys_argv' in data: | 
					
						
							|  |  |  |         sys.argv = data['sys_argv'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'dir' in data: | 
					
						
							|  |  |  |         os.chdir(data['dir']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'orig_dir' in data: | 
					
						
							|  |  |  |         process.ORIGINAL_DIR = data['orig_dir'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if 'main_path' in data: | 
					
						
							| 
									
										
										
										
											2011-01-30 01:24:08 +00:00
										 |  |  |         # XXX (ncoghlan): The following code makes several bogus | 
					
						
							|  |  |  |         # assumptions regarding the relationship between __file__ | 
					
						
							|  |  |  |         # and a module's real name. See PEP 302 and issue #10845 | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |         main_path = data['main_path'] | 
					
						
							|  |  |  |         main_name = os.path.splitext(os.path.basename(main_path))[0] | 
					
						
							|  |  |  |         if main_name == '__init__': | 
					
						
							|  |  |  |             main_name = os.path.basename(os.path.dirname(main_path)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-30 01:24:08 +00:00
										 |  |  |         if main_name == '__main__': | 
					
						
							|  |  |  |             main_module = sys.modules['__main__'] | 
					
						
							|  |  |  |             main_module.__file__ = main_path | 
					
						
							|  |  |  |         elif main_name != 'ipython': | 
					
						
							|  |  |  |             # Main modules not actually called __main__.py may | 
					
						
							|  |  |  |             # contain additional code that should still be executed | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |             import imp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if main_path is None: | 
					
						
							|  |  |  |                 dirs = None | 
					
						
							|  |  |  |             elif os.path.basename(main_path).startswith('__init__.py'): | 
					
						
							|  |  |  |                 dirs = [os.path.dirname(os.path.dirname(main_path))] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 dirs = [os.path.dirname(main_path)] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             assert main_name not in sys.modules, main_name | 
					
						
							| 
									
										
										
										
											2012-10-08 13:07:00 +01:00
										 |  |  |             sys.modules.pop('__mp_main__', None) | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |             file, path_name, etc = imp.find_module(main_name, dirs) | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2012-10-08 13:07:00 +01:00
										 |  |  |                 # We should not do 'imp.load_module("__main__", ...)' | 
					
						
							|  |  |  |                 # since that would execute 'if __name__ == "__main__"' | 
					
						
							|  |  |  |                 # clauses, potentially causing a psuedo fork bomb. | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                 main_module = imp.load_module( | 
					
						
							| 
									
										
										
										
											2012-10-08 13:07:00 +01:00
										 |  |  |                     '__mp_main__', file, path_name, etc | 
					
						
							| 
									
										
										
										
											2008-06-11 16:44:04 +00:00
										 |  |  |                     ) | 
					
						
							|  |  |  |             finally: | 
					
						
							|  |  |  |                 if file: | 
					
						
							|  |  |  |                     file.close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 13:07:00 +01:00
										 |  |  |             sys.modules['__main__'] = sys.modules['__mp_main__'] = main_module |