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