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

Side by Side Diff: Tools/Scripts/webkitpy/layout_tests/port/server_process.py

Issue 546133003: Reformat webkitpy.layout_tests w/ format-webkitpy. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 3 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 | Annotate | Revision Log
OLDNEW
1 # Copyright (C) 2010 Google Inc. All rights reserved. 1 # Copyright (C) 2010 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 def quote_data(data): 65 def quote_data(data):
66 txt = repr(data).replace('\\n', '\\n\n')[1:-1] 66 txt = repr(data).replace('\\n', '\\n\n')[1:-1]
67 lines = [] 67 lines = []
68 for l in txt.splitlines(): 68 for l in txt.splitlines():
69 m = _trailing_spaces_re.match(l) 69 m = _trailing_spaces_re.match(l)
70 if m: 70 if m:
71 l = m.group(1) + m.group(2).replace(' ', '\x20') 71 l = m.group(1) + m.group(2).replace(' ', '\x20')
72 lines.append(l) 72 lines.append(l)
73 return lines 73 return lines
74 74
75
75 class ServerProcess(object): 76 class ServerProcess(object):
77
76 """This class provides a wrapper around a subprocess that 78 """This class provides a wrapper around a subprocess that
77 implements a simple request/response usage model. The primary benefit 79 implements a simple request/response usage model. The primary benefit
78 is that reading responses takes a deadline, so that we don't ever block 80 is that reading responses takes a deadline, so that we don't ever block
79 indefinitely. The class also handles transparently restarting processes 81 indefinitely. The class also handles transparently restarting processes
80 as necessary to keep issuing commands.""" 82 as necessary to keep issuing commands."""
81 83
82 def __init__(self, port_obj, name, cmd, env=None, universal_newlines=False, treat_no_data_as_crash=False, 84 def __init__(self, port_obj, name, cmd, env=None, universal_newlines=False, treat_no_data_as_crash=False,
83 logging=False): 85 logging=False):
84 self._port = port_obj 86 self._port = port_obj
85 self._name = name # Should be the command name (e.g. content_shell, ima ge_diff) 87 self._name = name # Should be the command name (e.g. content_shell, ima ge_diff)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 self._output = str() # bytesarray() once we require Python 2.6 122 self._output = str() # bytesarray() once we require Python 2.6
121 self._error = str() # bytesarray() once we require Python 2.6 123 self._error = str() # bytesarray() once we require Python 2.6
122 self._crashed = False 124 self._crashed = False
123 self.timed_out = False 125 self.timed_out = False
124 126
125 def process_name(self): 127 def process_name(self):
126 return self._name 128 return self._name
127 129
128 def _start(self): 130 def _start(self):
129 if self._proc: 131 if self._proc:
130 raise ValueError("%s already running" % self._name) 132 raise ValueError('%s already running' % self._name)
131 self._reset() 133 self._reset()
132 # close_fds is a workaround for http://bugs.python.org/issue2320 134 # close_fds is a workaround for http://bugs.python.org/issue2320
133 close_fds = not self._host.platform.is_win() 135 close_fds = not self._host.platform.is_win()
134 if self._logging: 136 if self._logging:
135 env_str = '' 137 env_str = ''
136 if self._env: 138 if self._env:
137 env_str += '\n'.join("%s=%s" % (k, v) for k, v in self._env.item s()) + '\n' 139 env_str += '\n'.join('%s=%s' % (k, v) for k, v in self._env.item s()) + '\n'
138 _log.info('CMD: \n%s%s\n', env_str, _quote_cmd(self._cmd)) 140 _log.info('CMD: \n%s%s\n', env_str, _quote_cmd(self._cmd))
139 self._proc = self._host.executive.popen(self._cmd, stdin=self._host.exec utive.PIPE, 141 self._proc = self._host.executive.popen(self._cmd, stdin=self._host.exec utive.PIPE,
140 stdout=self._host.executive.PIPE, 142 stdout=self._host.executive.PIPE ,
141 stderr=self._host.executive.PIPE, 143 stderr=self._host.executive.PIPE ,
142 close_fds=close_fds, 144 close_fds=close_fds,
143 env=self._env, 145 env=self._env,
144 universal_newlines=self._universal_newlines) 146 universal_newlines=self._univers al_newlines)
145 self._pid = self._proc.pid 147 self._pid = self._proc.pid
146 fd = self._proc.stdout.fileno() 148 fd = self._proc.stdout.fileno()
147 if not self._use_win32_apis: 149 if not self._use_win32_apis:
148 fl = fcntl.fcntl(fd, fcntl.F_GETFL) 150 fl = fcntl.fcntl(fd, fcntl.F_GETFL)
149 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 151 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
150 fd = self._proc.stderr.fileno() 152 fd = self._proc.stderr.fileno()
151 fl = fcntl.fcntl(fd, fcntl.F_GETFL) 153 fl = fcntl.fcntl(fd, fcntl.F_GETFL)
152 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 154 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
153 155
154 def _handle_possible_interrupt(self): 156 def _handle_possible_interrupt(self):
(...skipping 16 matching lines...) Expand all
171 return None 173 return None
172 174
173 def write(self, bytes): 175 def write(self, bytes):
174 """Write a request to the subprocess. The subprocess is (re-)start()'ed 176 """Write a request to the subprocess. The subprocess is (re-)start()'ed
175 if is not already running.""" 177 if is not already running."""
176 if not self._proc: 178 if not self._proc:
177 self._start() 179 self._start()
178 try: 180 try:
179 self._log_data(' IN', bytes) 181 self._log_data(' IN', bytes)
180 self._proc.stdin.write(bytes) 182 self._proc.stdin.write(bytes)
181 except IOError, e: 183 except IOError as e:
182 self.stop(0.0) 184 self.stop(0.0)
183 # stop() calls _reset(), so we have to set crashed to True after cal ling stop(). 185 # stop() calls _reset(), so we have to set crashed to True after cal ling stop().
184 self._crashed = True 186 self._crashed = True
185 187
186 def _pop_stdout_line_if_ready(self): 188 def _pop_stdout_line_if_ready(self):
187 index_after_newline = self._output.find('\n') + 1 189 index_after_newline = self._output.find('\n') + 1
188 if index_after_newline > 0: 190 if index_after_newline > 0:
189 return self._pop_output_bytes(index_after_newline) 191 return self._pop_output_bytes(index_after_newline)
190 return None 192 return None
191 193
(...skipping 16 matching lines...) Expand all
208 def retrieve_bytes_from_buffers(): 210 def retrieve_bytes_from_buffers():
209 stdout_line = self._pop_stdout_line_if_ready() 211 stdout_line = self._pop_stdout_line_if_ready()
210 if stdout_line: 212 if stdout_line:
211 return stdout_line, None 213 return stdout_line, None
212 stderr_line = self._pop_stderr_line_if_ready() 214 stderr_line = self._pop_stderr_line_if_ready()
213 if stderr_line: 215 if stderr_line:
214 return None, stderr_line 216 return None, stderr_line
215 return None # Instructs the caller to keep waiting. 217 return None # Instructs the caller to keep waiting.
216 218
217 return_value = self._read(deadline, retrieve_bytes_from_buffers) 219 return_value = self._read(deadline, retrieve_bytes_from_buffers)
218 # FIXME: This is a bit of a hack around the fact that _read normally onl y returns one value, but this caller wants it to return two. 220 # FIXME: This is a bit of a hack around the fact that _read normally onl y
221 # returns one value, but this caller wants it to return two.
219 if return_value is None: 222 if return_value is None:
220 return None, None 223 return None, None
221 return return_value 224 return return_value
222 225
223 def read_stdout(self, deadline, size): 226 def read_stdout(self, deadline, size):
224 if size <= 0: 227 if size <= 0:
225 raise ValueError('ServerProcess.read() called with a non-positive si ze: %d ' % size) 228 raise ValueError('ServerProcess.read() called with a non-positive si ze: %d ' % size)
226 229
227 def retrieve_bytes_from_stdout_buffer(): 230 def retrieve_bytes_from_stdout_buffer():
228 if len(self._output) >= size: 231 if len(self._output) >= size:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 if self._proc.stdout.closed or self._proc.stderr.closed: 264 if self._proc.stdout.closed or self._proc.stderr.closed:
262 # If the process crashed and is using FIFOs, like Chromium Android, the 265 # If the process crashed and is using FIFOs, like Chromium Android, the
263 # stdout and stderr pipes will be closed. 266 # stdout and stderr pipes will be closed.
264 return 267 return
265 268
266 out_fd = self._proc.stdout.fileno() 269 out_fd = self._proc.stdout.fileno()
267 err_fd = self._proc.stderr.fileno() 270 err_fd = self._proc.stderr.fileno()
268 select_fds = (out_fd, err_fd) 271 select_fds = (out_fd, err_fd)
269 try: 272 try:
270 read_fds, _, _ = select.select(select_fds, [], select_fds, max(deadl ine - time.time(), 0)) 273 read_fds, _, _ = select.select(select_fds, [], select_fds, max(deadl ine - time.time(), 0))
271 except select.error, e: 274 except select.error as e:
272 # We can ignore EINVAL since it's likely the process just crashed an d we'll 275 # We can ignore EINVAL since it's likely the process just crashed an d we'll
273 # figure that out the next time through the loop in _read(). 276 # figure that out the next time through the loop in _read().
274 if e.args[0] == errno.EINVAL: 277 if e.args[0] == errno.EINVAL:
275 return 278 return
276 raise 279 raise
277 280
278 try: 281 try:
279 # Note that we may get no data during read() even though 282 # Note that we may get no data during read() even though
280 # select says we got something; see the select() man page 283 # select says we got something; see the select() man page
281 # on linux. I don't know if this happens on Mac OS and 284 # on linux. I don't know if this happens on Mac OS and
282 # other Unixen as well, but we don't bother special-casing 285 # other Unixen as well, but we don't bother special-casing
283 # Linux because it's relatively harmless either way. 286 # Linux because it's relatively harmless either way.
284 if out_fd in read_fds: 287 if out_fd in read_fds:
285 data = self._proc.stdout.read() 288 data = self._proc.stdout.read()
286 if not data and not stopping and (self._treat_no_data_as_crash o r self._proc.poll()): 289 if not data and not stopping and (self._treat_no_data_as_crash o r self._proc.poll()):
287 self._crashed = True 290 self._crashed = True
288 self._log_data('OUT', data) 291 self._log_data('OUT', data)
289 self._output += data 292 self._output += data
290 293
291 if err_fd in read_fds: 294 if err_fd in read_fds:
292 data = self._proc.stderr.read() 295 data = self._proc.stderr.read()
293 if not data and not stopping and (self._treat_no_data_as_crash o r self._proc.poll()): 296 if not data and not stopping and (self._treat_no_data_as_crash o r self._proc.poll()):
294 self._crashed = True 297 self._crashed = True
295 self._log_data('ERR', data) 298 self._log_data('ERR', data)
296 self._error += data 299 self._error += data
297 except IOError, e: 300 except IOError as e:
298 # We can ignore the IOErrors because we will detect if the subporces s crashed 301 # We can ignore the IOErrors because we will detect if the subporces s crashed
299 # the next time through the loop in _read() 302 # the next time through the loop in _read()
300 pass 303 pass
301 304
302 def _wait_for_data_and_update_buffers_using_win32_apis(self, deadline): 305 def _wait_for_data_and_update_buffers_using_win32_apis(self, deadline):
303 # See http://code.activestate.com/recipes/440554-module-to-allow-asynchr onous-subprocess-use-on-win/ 306 # See http://code.activestate.com/recipes/440554-module-to-allow-asynchr onous-subprocess-use-on-win/
304 # and http://docs.activestate.com/activepython/2.6/pywin32/modules.html 307 # and http://docs.activestate.com/activepython/2.6/pywin32/modules.html
305 # for documentation on all of these win32-specific modules. 308 # for documentation on all of these win32-specific modules.
306 now = time.time() 309 now = time.time()
307 out_fh = msvcrt.get_osfhandle(self._proc.stdout.fileno()) 310 out_fh = msvcrt.get_osfhandle(self._proc.stdout.fileno())
(...skipping 12 matching lines...) Expand all
320 time.sleep(0.01) 323 time.sleep(0.01)
321 now = time.time() 324 now = time.time()
322 return 325 return
323 326
324 def _non_blocking_read_win32(self, handle): 327 def _non_blocking_read_win32(self, handle):
325 try: 328 try:
326 _, avail, _ = win32pipe.PeekNamedPipe(handle, 0) 329 _, avail, _ = win32pipe.PeekNamedPipe(handle, 0)
327 if avail > 0: 330 if avail > 0:
328 _, buf = win32file.ReadFile(handle, avail, None) 331 _, buf = win32file.ReadFile(handle, avail, None)
329 return buf 332 return buf
330 except Exception, e: 333 except Exception as e:
331 if e[0] not in (109, errno.ESHUTDOWN): # 109 == win32 ERROR_BROKEN_ PIPE 334 if e[0] not in (109, errno.ESHUTDOWN): # 109 == win32 ERROR_BROKEN_ PIPE
332 raise 335 raise
333 return None 336 return None
334 337
335 def has_crashed(self): 338 def has_crashed(self):
336 if not self._crashed and self.poll(): 339 if not self._crashed and self.poll():
337 self._crashed = True 340 self._crashed = True
338 self._handle_possible_interrupt() 341 self._handle_possible_interrupt()
339 return self._crashed 342 return self._crashed
340 343
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 self._proc.wait() 408 self._proc.wait()
406 409
407 def replace_outputs(self, stdout, stderr): 410 def replace_outputs(self, stdout, stderr):
408 assert self._proc 411 assert self._proc
409 if stdout: 412 if stdout:
410 self._proc.stdout.close() 413 self._proc.stdout.close()
411 self._proc.stdout = stdout 414 self._proc.stdout = stdout
412 if stderr: 415 if stderr:
413 self._proc.stderr.close() 416 self._proc.stderr.close()
414 self._proc.stderr = stderr 417 self._proc.stderr = stderr
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698