Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(600)

Side by Side Diff: build/android/pylib/cmd_helper.py

Issue 1284283002: [Android] Add partial output to TimeoutError raised in cmd_helper. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | build/android/pylib/perf/test_runner.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 logging 7 import logging
8 import os 8 import os
9 import pipes 9 import pipes
10 import select 10 import select
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 if stderr: 153 if stderr:
154 logging.critical(stderr) 154 logging.critical(stderr)
155 if len(stdout) > 4096: 155 if len(stdout) > 4096:
156 logging.debug('Truncated output:') 156 logging.debug('Truncated output:')
157 logging.debug(stdout[:4096]) 157 logging.debug(stdout[:4096])
158 return (pipe.returncode, stdout) 158 return (pipe.returncode, stdout)
159 159
160 160
161 class TimeoutError(Exception): 161 class TimeoutError(Exception):
162 """Module-specific timeout exception.""" 162 """Module-specific timeout exception."""
163 pass 163
164 def __init__(self, output=None):
165 super(TimeoutError, self).__init__()
166 self._output = output
167
168 @property
169 def output(self):
170 return self._output
164 171
165 172
166 def _IterProcessStdout(process, timeout=None, buffer_size=4096, 173 def _IterProcessStdout(process, timeout=None, buffer_size=4096,
167 poll_interval=1): 174 poll_interval=1):
168 assert fcntl, 'fcntl module is required' 175 assert fcntl, 'fcntl module is required'
169 try: 176 try:
170 # Enable non-blocking reads from the child's stdout. 177 # Enable non-blocking reads from the child's stdout.
171 child_fd = process.stdout.fileno() 178 child_fd = process.stdout.fileno()
172 fl = fcntl.fcntl(child_fd, fcntl.F_GETFL) 179 fl = fcntl.fcntl(child_fd, fcntl.F_GETFL)
173 fcntl.fcntl(child_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 180 fcntl.fcntl(child_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
174 181
175 end_time = (time.time() + timeout) if timeout else None 182 end_time = (time.time() + timeout) if timeout else None
176 while True: 183 while True:
177 if end_time and time.time() > end_time: 184 if end_time and time.time() > end_time:
178 raise TimeoutError 185 raise TimeoutError()
179 read_fds, _, _ = select.select([child_fd], [], [], poll_interval) 186 read_fds, _, _ = select.select([child_fd], [], [], poll_interval)
180 if child_fd in read_fds: 187 if child_fd in read_fds:
181 data = os.read(child_fd, buffer_size) 188 data = os.read(child_fd, buffer_size)
182 if not data: 189 if not data:
183 break 190 break
184 yield data 191 yield data
185 if process.poll() is not None: 192 if process.poll() is not None:
186 break 193 break
187 finally: 194 finally:
188 try: 195 try:
(...skipping 20 matching lines...) Expand all
209 logfile: Optional file-like object that will receive output from the 216 logfile: Optional file-like object that will receive output from the
210 command as it is running. 217 command as it is running.
211 218
212 Returns: 219 Returns:
213 The 2-tuple (exit code, output). 220 The 2-tuple (exit code, output).
214 """ 221 """
215 _ValidateAndLogCommand(args, cwd, shell) 222 _ValidateAndLogCommand(args, cwd, shell)
216 output = StringIO.StringIO() 223 output = StringIO.StringIO()
217 process = Popen(args, cwd=cwd, shell=shell, stdout=subprocess.PIPE, 224 process = Popen(args, cwd=cwd, shell=shell, stdout=subprocess.PIPE,
218 stderr=subprocess.STDOUT) 225 stderr=subprocess.STDOUT)
219 for data in _IterProcessStdout(process, timeout=timeout): 226 try:
220 if logfile: 227 for data in _IterProcessStdout(process, timeout=timeout):
221 logfile.write(data) 228 if logfile:
222 output.write(data) 229 logfile.write(data)
230 output.write(data)
231 except TimeoutError:
232 raise TimeoutError(output.getvalue())
233
223 return process.returncode, output.getvalue() 234 return process.returncode, output.getvalue()
224 235
225 236
226 def IterCmdOutputLines(args, timeout=None, cwd=None, shell=False, 237 def IterCmdOutputLines(args, timeout=None, cwd=None, shell=False,
227 check_status=True): 238 check_status=True):
228 """Executes a subprocess and continuously yields lines from its output. 239 """Executes a subprocess and continuously yields lines from its output.
229 240
230 Args: 241 Args:
231 args: List of arguments to the program, the program to execute is the first 242 args: List of arguments to the program, the program to execute is the first
232 element. 243 element.
(...skipping 19 matching lines...) Expand all
252 buffer_output += data 263 buffer_output += data
253 has_incomplete_line = buffer_output[-1] not in '\r\n' 264 has_incomplete_line = buffer_output[-1] not in '\r\n'
254 lines = buffer_output.splitlines() 265 lines = buffer_output.splitlines()
255 buffer_output = lines.pop() if has_incomplete_line else '' 266 buffer_output = lines.pop() if has_incomplete_line else ''
256 for line in lines: 267 for line in lines:
257 yield line 268 yield line
258 if buffer_output: 269 if buffer_output:
259 yield buffer_output 270 yield buffer_output
260 if check_status and process.returncode: 271 if check_status and process.returncode:
261 raise subprocess.CalledProcessError(process.returncode, cmd) 272 raise subprocess.CalledProcessError(process.returncode, cmd)
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/perf/test_runner.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698