|  | import os | 
|  | import signal | 
|  |  | 
|  | from . import util | 
|  |  | 
|  | __all__ = ['Popen'] | 
|  |  | 
|  | # | 
|  | # Start child process using fork | 
|  | # | 
|  |  | 
|  | class Popen(object): | 
|  | method = 'fork' | 
|  |  | 
|  | def __init__(self, process_obj): | 
|  | util._flush_std_streams() | 
|  | self.returncode = None | 
|  | self.finalizer = None | 
|  | self._launch(process_obj) | 
|  |  | 
|  | def duplicate_for_child(self, fd): | 
|  | return fd | 
|  |  | 
|  | def poll(self, flag=os.WNOHANG): | 
|  | if self.returncode is None: | 
|  | try: | 
|  | pid, sts = os.waitpid(self.pid, flag) | 
|  | except OSError: | 
|  | # Child process not yet created. See #1731717 | 
|  | # e.errno == errno.ECHILD == 10 | 
|  | return None | 
|  | if pid == self.pid: | 
|  | self.returncode = os.waitstatus_to_exitcode(sts) | 
|  | return self.returncode | 
|  |  | 
|  | def wait(self, timeout=None): | 
|  | if self.returncode is None: | 
|  | if timeout is not None: | 
|  | from multiprocessing.connection import wait | 
|  | if not wait([self.sentinel], timeout): | 
|  | return None | 
|  | # This shouldn't block if wait() returned successfully. | 
|  | return self.poll(os.WNOHANG if timeout == 0.0 else 0) | 
|  | return self.returncode | 
|  |  | 
|  | def _send_signal(self, sig): | 
|  | if self.returncode is None: | 
|  | try: | 
|  | os.kill(self.pid, sig) | 
|  | except ProcessLookupError: | 
|  | pass | 
|  | except OSError: | 
|  | if self.wait(timeout=0.1) is None: | 
|  | raise | 
|  |  | 
|  | def terminate(self): | 
|  | self._send_signal(signal.SIGTERM) | 
|  |  | 
|  | def kill(self): | 
|  | self._send_signal(signal.SIGKILL) | 
|  |  | 
|  | def _launch(self, process_obj): | 
|  | code = 1 | 
|  | parent_r, child_w = os.pipe() | 
|  | child_r, parent_w = os.pipe() | 
|  | self.pid = os.fork() | 
|  | if self.pid == 0: | 
|  | try: | 
|  | os.close(parent_r) | 
|  | os.close(parent_w) | 
|  | code = process_obj._bootstrap(parent_sentinel=child_r) | 
|  | finally: | 
|  | os._exit(code) | 
|  | else: | 
|  | os.close(child_w) | 
|  | os.close(child_r) | 
|  | self.finalizer = util.Finalize(self, util.close_fds, | 
|  | (parent_r, parent_w,)) | 
|  | self.sentinel = parent_r | 
|  |  | 
|  | def close(self): | 
|  | if self.finalizer is not None: | 
|  | self.finalizer() |