OLD | NEW |
1 # coding=utf8 | 1 # coding=utf8 |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 """Collection of subprocess wrapper functions. | 5 """Collection of subprocess wrapper functions. |
6 | 6 |
7 In theory you shouldn't need anything else in subprocess, or this module failed. | 7 In theory you shouldn't need anything else in subprocess, or this module failed. |
8 """ | 8 """ |
9 | 9 |
10 from __future__ import with_statement | 10 from __future__ import with_statement |
11 import errno | 11 import errno |
12 import logging | 12 import logging |
13 import os | 13 import os |
14 import subprocess | 14 import subprocess |
15 import sys | 15 import sys |
16 import tempfile | 16 import tempfile |
17 import time | 17 import time |
18 import threading | 18 import threading |
19 | 19 |
| 20 |
20 # Constants forwarded from subprocess. | 21 # Constants forwarded from subprocess. |
21 PIPE = subprocess.PIPE | 22 PIPE = subprocess.PIPE |
22 STDOUT = subprocess.STDOUT | 23 STDOUT = subprocess.STDOUT |
23 # Sends stdout or stderr to os.devnull. | 24 # Sends stdout or stderr to os.devnull. |
24 VOID = object() | 25 VOID = object() |
25 # Error code when a process was killed because it timed out. | 26 # Error code when a process was killed because it timed out. |
26 TIMED_OUT = -2001 | 27 TIMED_OUT = -2001 |
27 | 28 |
28 # Globals. | 29 # Globals. |
29 # Set to True if you somehow need to disable this hack. | 30 # Set to True if you somehow need to disable this hack. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 # Create a temporary file to workaround python's deadlock. | 176 # Create a temporary file to workaround python's deadlock. |
176 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait | 177 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait |
177 # When the pipe fills up, it will deadlock this process. Using a real | 178 # When the pipe fills up, it will deadlock this process. Using a real |
178 # file works around that issue. | 179 # file works around that issue. |
179 kwargs[stream] = open(os.devnull, 'w') | 180 kwargs[stream] = open(os.devnull, 'w') |
180 | 181 |
181 fix('stdout') | 182 fix('stdout') |
182 fix('stderr') | 183 fix('stderr') |
183 | 184 |
184 self.start = time.time() | 185 self.start = time.time() |
| 186 self.shell = kwargs.get('shell', None) |
185 # Silence pylint on MacOSX | 187 # Silence pylint on MacOSX |
186 self.returncode = None | 188 self.returncode = None |
| 189 |
187 try: | 190 try: |
188 super(Popen, self).__init__(args, **kwargs) | 191 super(Popen, self).__init__(args, **kwargs) |
189 except OSError, e: | 192 except OSError, e: |
190 if e.errno == errno.EAGAIN and sys.platform == 'cygwin': | 193 if e.errno == errno.EAGAIN and sys.platform == 'cygwin': |
191 # Convert fork() emulation failure into a CygwinRebaseError(). | 194 # Convert fork() emulation failure into a CygwinRebaseError(). |
192 raise CygwinRebaseError( | 195 raise CygwinRebaseError( |
193 e.errno, | 196 e.errno, |
194 args, | 197 args, |
195 kwargs.get('cwd'), | 198 kwargs.get('cwd'), |
196 None, | 199 None, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 else: | 234 else: |
232 return proc.communicate(), proc.returncode | 235 return proc.communicate(), proc.returncode |
233 | 236 |
234 # Create a temporary file to workaround python's deadlock. | 237 # Create a temporary file to workaround python's deadlock. |
235 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait | 238 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait |
236 # When the pipe fills up, it will deadlock this process. Using a real file | 239 # When the pipe fills up, it will deadlock this process. Using a real file |
237 # works around that issue. | 240 # works around that issue. |
238 with tempfile.TemporaryFile() as buff: | 241 with tempfile.TemporaryFile() as buff: |
239 kwargs['stdout'] = buff | 242 kwargs['stdout'] = buff |
240 proc = Popen(args, **kwargs) | 243 proc = Popen(args, **kwargs) |
| 244 if proc.shell: |
| 245 raise TypeError( |
| 246 'Using timeout and shell simultaneously will cause a process leak ' |
| 247 'since the shell will be killed instead of the child process.') |
241 if stdin is not None: | 248 if stdin is not None: |
242 proc.stdin.write(stdin) | 249 proc.stdin.write(stdin) |
243 while proc.returncode is None: | 250 while proc.returncode is None: |
244 proc.poll() | 251 proc.poll() |
245 if timeout and (time.time() - proc.start) > timeout: | 252 if timeout and (time.time() - proc.start) > timeout: |
246 proc.kill() | 253 proc.kill() |
247 proc.wait() | 254 proc.wait() |
248 # It's -9 on linux and 1 on Windows. Standardize to TIMED_OUT. | 255 # It's -9 on linux and 1 on Windows. Standardize to TIMED_OUT. |
249 proc.returncode = TIMED_OUT | 256 proc.returncode = TIMED_OUT |
250 time.sleep(0.001) | 257 time.sleep(0.001) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 | 314 |
308 - Throws if return code is not 0. | 315 - Throws if return code is not 0. |
309 - Works even prior to python 2.7. | 316 - Works even prior to python 2.7. |
310 - Blocks stdin by default if not specified since no output will be visible. | 317 - Blocks stdin by default if not specified since no output will be visible. |
311 - As per doc, "The stdout argument is not allowed as it is used internally." | 318 - As per doc, "The stdout argument is not allowed as it is used internally." |
312 """ | 319 """ |
313 kwargs.setdefault('stdin', VOID) | 320 kwargs.setdefault('stdin', VOID) |
314 if 'stdout' in kwargs: | 321 if 'stdout' in kwargs: |
315 raise ValueError('stdout argument not allowed, it will be overridden.') | 322 raise ValueError('stdout argument not allowed, it will be overridden.') |
316 return check_call_out(args, stdout=PIPE, **kwargs)[0] | 323 return check_call_out(args, stdout=PIPE, **kwargs)[0] |
OLD | NEW |