OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """A wrapper for subprocess to make calling shell commands easier.""" | 5 """A wrapper for subprocess to make calling shell commands easier.""" |
6 | 6 |
7 import os | 7 import os |
8 import logging | 8 import logging |
| 9 import signal |
9 import subprocess | 10 import subprocess |
| 11 import tempfile |
10 | 12 |
11 import constants | 13 import constants |
12 | 14 |
13 | 15 |
| 16 def _Call(args, stdout=None, stderr=None, shell=None, cwd=None): |
| 17 return subprocess.call( |
| 18 args=args, cwd=cwd, stdout=stdout, stderr=stderr, |
| 19 shell=shell, close_fds=True, |
| 20 preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)) |
| 21 |
| 22 |
14 def RunCmd(args, cwd=None): | 23 def RunCmd(args, cwd=None): |
15 """Opens a subprocess to execute a program and returns its return value. | 24 """Opens a subprocess to execute a program and returns its return value. |
16 | 25 |
17 Args: | 26 Args: |
18 args: A string or a sequence of program arguments. The program to execute is | 27 args: A string or a sequence of program arguments. The program to execute is |
19 the string or the first item in the args sequence. | 28 the string or the first item in the args sequence. |
20 cwd: If not None, the subprocess's current directory will be changed to | 29 cwd: If not None, the subprocess's current directory will be changed to |
21 |cwd| before it's executed. | 30 |cwd| before it's executed. |
22 | 31 |
23 Returns: | 32 Returns: |
24 Return code from the command execution. | 33 Return code from the command execution. |
25 """ | 34 """ |
26 logging.info(str(args) + ' ' + (cwd or '')) | 35 logging.info(str(args) + ' ' + (cwd or '')) |
27 return subprocess.call(args, cwd=cwd) | 36 return _Call(args, cwd=cwd) |
28 | 37 |
29 | 38 |
30 def GetCmdOutput(args, cwd=None, shell=False): | 39 def GetCmdOutput(args, cwd=None, shell=False): |
31 """Open a subprocess to execute a program and returns its output. | 40 """Open a subprocess to execute a program and returns its output. |
32 | 41 |
33 Args: | 42 Args: |
34 args: A string or a sequence of program arguments. The program to execute is | 43 args: A string or a sequence of program arguments. The program to execute is |
35 the string or the first item in the args sequence. | 44 the string or the first item in the args sequence. |
36 cwd: If not None, the subprocess's current directory will be changed to | 45 cwd: If not None, the subprocess's current directory will be changed to |
37 |cwd| before it's executed. | 46 |cwd| before it's executed. |
(...skipping 14 matching lines...) Expand all Loading... |
52 args: A string or a sequence of program arguments. The program to execute is | 61 args: A string or a sequence of program arguments. The program to execute is |
53 the string or the first item in the args sequence. | 62 the string or the first item in the args sequence. |
54 cwd: If not None, the subprocess's current directory will be changed to | 63 cwd: If not None, the subprocess's current directory will be changed to |
55 |cwd| before it's executed. | 64 |cwd| before it's executed. |
56 shell: Whether to execute args as a shell command. | 65 shell: Whether to execute args as a shell command. |
57 | 66 |
58 Returns: | 67 Returns: |
59 The tuple (exit code, output). | 68 The tuple (exit code, output). |
60 """ | 69 """ |
61 logging.info(str(args) + ' ' + (cwd or '')) | 70 logging.info(str(args) + ' ' + (cwd or '')) |
62 p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE, | 71 tmpout = tempfile.TemporaryFile(bufsize=0) |
63 stderr=subprocess.PIPE, shell=shell) | 72 tmperr = tempfile.TemporaryFile(bufsize=0) |
64 stdout, stderr = p.communicate() | 73 exit_code = _Call(args, cwd=cwd, stdout=tmpout, stderr=tmperr, shell=shell) |
65 exit_code = p.returncode | 74 tmperr.seek(0) |
| 75 stderr = tmperr.read() |
| 76 tmperr.close() |
66 if stderr: | 77 if stderr: |
67 logging.critical(stderr) | 78 logging.critical(stderr) |
| 79 tmpout.seek(0) |
| 80 stdout = tmpout.read() |
| 81 tmpout.close() |
68 logging.info(stdout[:4096]) # Truncate output longer than 4k. | 82 logging.info(stdout[:4096]) # Truncate output longer than 4k. |
69 return (exit_code, stdout) | 83 return (exit_code, stdout) |
70 | 84 |
71 | 85 |
72 class OutDirectory(object): | 86 class OutDirectory(object): |
73 _out_directory = os.path.join(constants.CHROME_DIR, 'out') | 87 _out_directory = os.path.join(constants.CHROME_DIR, 'out') |
74 @staticmethod | 88 @staticmethod |
75 def set(out_directory): | 89 def set(out_directory): |
76 OutDirectory._out_directory = out_directory | 90 OutDirectory._out_directory = out_directory |
77 @staticmethod | 91 @staticmethod |
78 def get(): | 92 def get(): |
79 return OutDirectory._out_directory | 93 return OutDirectory._out_directory |
OLD | NEW |