1import os 2import sys 3import signal 4 5from . import util 6 7__all__ = ['Popen'] 8 9# 10# Start child process using fork 11# 12 13class Popen(object): 14 method = 'fork' 15 16 def __init__(self, process_obj): 17 sys.stdout.flush() 18 sys.stderr.flush() 19 self.returncode = None 20 self._launch(process_obj) 21 22 def duplicate_for_child(self, fd): 23 return fd 24 25 def poll(self, flag=os.WNOHANG): 26 if self.returncode is None: 27 while True: 28 try: 29 pid, sts = os.waitpid(self.pid, flag) 30 except OSError as e: 31 # Child process not yet created. See #1731717 32 # e.errno == errno.ECHILD == 10 33 return None 34 else: 35 break 36 if pid == self.pid: 37 if os.WIFSIGNALED(sts): 38 self.returncode = -os.WTERMSIG(sts) 39 else: 40 assert os.WIFEXITED(sts) 41 self.returncode = os.WEXITSTATUS(sts) 42 return self.returncode 43 44 def wait(self, timeout=None): 45 if self.returncode is None: 46 if timeout is not None: 47 from multiprocessing.connection import wait 48 if not wait([self.sentinel], timeout): 49 return None 50 # This shouldn't block if wait() returned successfully. 51 return self.poll(os.WNOHANG if timeout == 0.0 else 0) 52 return self.returncode 53 54 def terminate(self): 55 if self.returncode is None: 56 try: 57 os.kill(self.pid, signal.SIGTERM) 58 except ProcessLookupError: 59 pass 60 except OSError: 61 if self.wait(timeout=0.1) is None: 62 raise 63 64 def _launch(self, process_obj): 65 code = 1 66 parent_r, child_w = os.pipe() 67 self.pid = os.fork() 68 if self.pid == 0: 69 try: 70 os.close(parent_r) 71 if 'random' in sys.modules: 72 import random 73 random.seed() 74 code = process_obj._bootstrap() 75 finally: 76 os._exit(code) 77 else: 78 os.close(child_w) 79 util.Finalize(self, os.close, (parent_r,)) 80 self.sentinel = parent_r 81