runtime/spawn_subprocess.py
changeset 3881 0b3ac94f494c
parent 3821 f7bc4e5832be
parent 3860 a1d7187b8402
equal deleted inserted replaced
3880:89549813a6c1 3881:0b3ac94f494c
    13 PIPE = "42"
    13 PIPE = "42"
    14 
    14 
    15 fsencoding = sys.getfilesystemencoding()
    15 fsencoding = sys.getfilesystemencoding()
    16 
    16 
    17 class Popen(object):
    17 class Popen(object):
    18     def __init__(self, args, stdin=None, stdout=None):
    18     def __init__(self, args, stdin=None, stdout=None, stderr=None):
    19         self.returncode = None
    19         self.returncode = None
    20         self.stdout = None
    20         self.stdout = None
       
    21         self.stderr = None
    21         self.stdin = None
    22         self.stdin = None
    22         # TODO: stderr
       
    23         file_actions = posix_spawn.FileActions()
    23         file_actions = posix_spawn.FileActions()
    24         if stdout is not None:
    24         if stdout is not None:
    25             # child's stdout, child 2 parent pipe
    25             # child's stdout, child 2 parent pipe
       
    26             c1pread, c1pwrite = os.pipe()
       
    27             # attach child's stdout to writing en of c1p pipe
       
    28             file_actions.add_dup2(c1pwrite, 1)
       
    29             # close other end
       
    30             file_actions.add_close(c1pread)
       
    31         if stderr is not None:
       
    32             # child's stderr, child 2 parent pipe
    26             c2pread, c2pwrite = os.pipe()
    33             c2pread, c2pwrite = os.pipe()
    27             # attach child's stdout to writing en of c2p pipe
    34             # attach child's stderr to writing en of c2p pipe
    28             file_actions.add_dup2(c2pwrite, 1)
    35             file_actions.add_dup2(c2pwrite, 2)
    29             # close other end
    36             # close other end
    30             file_actions.add_close(c2pread)
    37             file_actions.add_close(c2pread)
    31         if stdin is not None:
    38         if stdin is not None:
    32             # child's stdin, parent to child pipe
    39             # child's stdin, parent to child pipe
    33             p2cread, p2cwrite = os.pipe()
    40             p2cread, p2cwrite = os.pipe()
    36             # close other end
    43             # close other end
    37             file_actions.add_close(p2cwrite)
    44             file_actions.add_close(p2cwrite)
    38         args = [s.encode(fsencoding) for s in args if type(s)==str]
    45         args = [s.encode(fsencoding) for s in args if type(s)==str]
    39         self.pid = posix_spawn.posix_spawnp(args[0], args, file_actions=file_actions)
    46         self.pid = posix_spawn.posix_spawnp(args[0], args, file_actions=file_actions)
    40         if stdout is not None:
    47         if stdout is not None:
    41             self.stdout = os.fdopen(c2pread)
    48             self.stdout = os.fdopen(c1pread)
       
    49             os.close(c1pwrite)
       
    50         if stderr is not None:
       
    51             self.stderr = os.fdopen(c2pread)
    42             os.close(c2pwrite)
    52             os.close(c2pwrite)
    43         if stdin is not None:
    53         if stdin is not None:
    44             self.stdin = os.fdopen(p2cwrite, 'w')
    54             self.stdin = os.fdopen(p2cwrite, 'w')
    45             os.close(p2cread)
    55             os.close(p2cread)
    46 
    56 
    50 
    60 
    51     def communicate(self):
    61     def communicate(self):
    52         if self.stdin is not None:
    62         if self.stdin is not None:
    53             self.stdin.close()
    63             self.stdin.close()
    54             self.stdin = None
    64             self.stdin = None
       
    65 
    55         if self.stdout is not None:
    66         if self.stdout is not None:
    56             stdoutdata = self.stdout.read()
    67             stdoutdata = self.stdout.read()
    57         else:
    68         else:
    58             stdoutdata = ""
    69             stdoutdata = ""
    59 
    70 
    60         # TODO
    71         if self.stderr is not None:
    61         stderrdata = ""
    72             stderrdata = self.stderr.read()
       
    73         else:
       
    74             stderrdata = ""
    62 
    75 
    63         self._wait()
    76         self._wait()
       
    77 
    64         if self.stdout is not None:
    78         if self.stdout is not None:
    65             self.stdout.close()
    79             self.stdout.close()
    66             self.stdout = None
    80             self.stdout = None
       
    81 
       
    82         if self.stderr is not None:
       
    83             self.stderr.close()
       
    84             self.stderr = None
    67 
    85 
    68         return (stdoutdata, stderrdata)
    86         return (stdoutdata, stderrdata)
    69 
    87 
    70     def wait(self):
    88     def wait(self):
    71         if self.stdin is not None:
    89         if self.stdin is not None:
    72             self.stdin.close()
    90             self.stdin.close()
    73             self.stdin = None
    91             self.stdin = None
       
    92 
    74         self._wait()
    93         self._wait()
       
    94 
    75         if self.stdout is not None:
    95         if self.stdout is not None:
    76             self.stdout.close()
    96             self.stdout.close()
    77             self.stdout = None
    97             self.stdout = None
       
    98 
       
    99         if self.stderr is not None:
       
   100             self.stderr.close()
       
   101             self.stderr = None
       
   102 
    78         return self.returncode
   103         return self.returncode
    79 
   104 
    80     def poll(self):
   105     def poll(self):
    81         if self.returncode is None:
   106         if self.returncode is None:
    82             pid, ret = os.waitpid(self.pid, os.WNOHANG)
   107             pid, ret = os.waitpid(self.pid, os.WNOHANG)
    84                 self.returncode = ret
   109                 self.returncode = ret
    85 
   110 
    86                 if self.stdin is not None:
   111                 if self.stdin is not None:
    87                     self.stdin.close()
   112                     self.stdin.close()
    88                     self.stdin = None
   113                     self.stdin = None
       
   114 
    89                 if self.stdout is not None:
   115                 if self.stdout is not None:
    90                     self.stdout.close()
   116                     self.stdout.close()
    91                     self.stdout = None
   117                     self.stdout = None
       
   118 
       
   119                 if self.stderr is not None:
       
   120                     self.stderr.close()
       
   121                     self.stderr = None
    92 
   122 
    93         return self.returncode
   123         return self.returncode
    94 
   124 
    95     def kill(self):
   125     def kill(self):
    96         os.kill(self.pid, signal.SIGKILL)
   126         os.kill(self.pid, signal.SIGKILL)
    97 
   127 
    98         if self.stdin is not None:
   128         if self.stdin is not None:
    99             self.stdin.close()
   129             self.stdin.close()
   100             self.stdin = None
   130             self.stdin = None
       
   131 
   101         if self.stdout is not None:
   132         if self.stdout is not None:
   102             self.stdout.close()
   133             self.stdout.close()
   103             self.stdout = None
   134             self.stdout = None
       
   135 
       
   136         if self.stderr is not None:
       
   137             self.stderr.close()
       
   138             self.stderr = None
   104 
   139 
   105 
   140 
   106 def call(*args):
   141 def call(*args):
   107     cmd = []
   142     cmd = []
   108     if isinstance(args[0], str):
   143     if isinstance(args[0], str):