15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2010 Google Inc. All rights reserved. 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# modification, are permitted provided that the following conditions are 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# met: 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# * Redistributions of source code must retain the above copyright 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# notice, this list of conditions and the following disclaimer. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# * Redistributions in binary form must reproduce the above 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# copyright notice, this list of conditions and the following disclaimer 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# in the documentation and/or other materials provided with the 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# distribution. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# * Neither the Google name nor the names of its 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# contributors may be used to endorse or promote products derived from 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# this software without specific prior written permission. 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)"""Package that implements the ServerProcess wrapper class""" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import errno 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import logging 33e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)import re 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import signal 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import sys 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import time 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Note that although win32 python does provide an implementation of 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# the win32 select API, it only works on sockets, and not on the named pipes 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# used by subprocess, so we have to use the native APIs directly. 41e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)_quote_cmd = None 42e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if sys.platform == 'win32': 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) import msvcrt 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) import win32pipe 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) import win32file 47e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) import subprocess 48e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) _quote_cmd = subprocess.list2cmdline 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)else: 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) import fcntl 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) import os 52e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) import pipes 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) import select 54e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) _quote_cmd = lambda cmdline: ' '.join(pipes.quote(arg) for arg in cmdline) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from webkitpy.common.system.executive import ScriptError 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)_log = logging.getLogger(__name__) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 62e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)_trailing_spaces_re = re.compile('(.*[^ ])?( +)$') 63e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 64e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 65e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)def quote_data(data): 66e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) txt = repr(data).replace('\\n', '\\n\n')[1:-1] 67e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) lines = [] 68e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) for l in txt.splitlines(): 69e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) m = _trailing_spaces_re.match(l) 70e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if m: 71e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) l = m.group(1) + m.group(2).replace(' ', '\x20') 72e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) lines.append(l) 73e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) return lines 74e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class ServerProcess(object): 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """This class provides a wrapper around a subprocess that 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) implements a simple request/response usage model. The primary benefit 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) is that reading responses takes a deadline, so that we don't ever block 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) indefinitely. The class also handles transparently restarting processes 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) as necessary to keep issuing commands.""" 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 82e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) def __init__(self, port_obj, name, cmd, env=None, universal_newlines=False, treat_no_data_as_crash=False, 83e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) logging=False): 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._port = port_obj 85f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) self._name = name # Should be the command name (e.g. content_shell, image_diff) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._cmd = cmd 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._env = env 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Set if the process outputs non-standard newlines like '\r\n' or '\r'. 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Don't set if there will be binary data or the data must be ASCII encoded. 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._universal_newlines = universal_newlines 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._treat_no_data_as_crash = treat_no_data_as_crash 92e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) self._logging = logging 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._host = self._port.host 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._pid = None 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._reset() 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # See comment in imports for why we need the win32 APIs and can't just use select. 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # FIXME: there should be a way to get win32 vs. cygwin from platforminfo. 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._use_win32_apis = sys.platform == 'win32' 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def name(self): 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._name 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def pid(self): 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._pid 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _reset(self): 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if getattr(self, '_proc', None): 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.stdin: 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdin.close() 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdin = None 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.stdout: 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdout.close() 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdout = None 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.stderr: 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stderr.close() 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stderr = None 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc = None 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._output = str() # bytesarray() once we require Python 2.6 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._error = str() # bytesarray() once we require Python 2.6 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._crashed = False 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self.timed_out = False 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def process_name(self): 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._name 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _start(self): 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc: 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise ValueError("%s already running" % self._name) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._reset() 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # close_fds is a workaround for http://bugs.python.org/issue2320 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close_fds = not self._host.platform.is_win() 134e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if self._logging: 135e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) env_str = '' 136e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if self._env: 137e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) env_str += '\n'.join("%s=%s" % (k, v) for k, v in self._env.items()) + '\n' 138e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) _log.info('CMD: \n%s%s\n', env_str, _quote_cmd(self._cmd)) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc = self._host.executive.popen(self._cmd, stdin=self._host.executive.PIPE, 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stdout=self._host.executive.PIPE, 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stderr=self._host.executive.PIPE, 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) close_fds=close_fds, 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) env=self._env, 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) universal_newlines=self._universal_newlines) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._pid = self._proc.pid 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fd = self._proc.stdout.fileno() 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not self._use_win32_apis: 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fl = fcntl.fcntl(fd, fcntl.F_GETFL) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fd = self._proc.stderr.fileno() 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fl = fcntl.fcntl(fd, fcntl.F_GETFL) 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _handle_possible_interrupt(self): 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """This routine checks to see if the process crashed or exited 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) because of a keyboard interrupt and raises KeyboardInterrupt 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) accordingly.""" 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # FIXME: Linux and Mac set the returncode to -signal.SIGINT if a 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # subprocess is killed with a ctrl^C. Previous comments in this 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # routine said that supposedly Windows returns 0xc000001d, but that's not what 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # -1073741510 evaluates to. Figure out what the right value is 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # for win32 and cygwin here ... 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.returncode in (-1073741510, -signal.SIGINT): 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise KeyboardInterrupt 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def poll(self): 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """Check to see if the underlying process is running; returns None 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if it still is (wrapper around subprocess.poll).""" 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc: 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._proc.poll() 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def write(self, bytes): 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """Write a request to the subprocess. The subprocess is (re-)start()'ed 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if is not already running.""" 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not self._proc: 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._start() 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try: 179e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) self._log_data(' IN', bytes) 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdin.write(bytes) 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) except IOError, e: 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self.stop(0.0) 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # stop() calls _reset(), so we have to set crashed to True after calling stop(). 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._crashed = True 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _pop_stdout_line_if_ready(self): 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) index_after_newline = self._output.find('\n') + 1 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if index_after_newline > 0: 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._pop_output_bytes(index_after_newline) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _pop_stderr_line_if_ready(self): 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) index_after_newline = self._error.find('\n') + 1 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if index_after_newline > 0: 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._pop_error_bytes(index_after_newline) 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def pop_all_buffered_stderr(self): 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._pop_error_bytes(len(self._error)) 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def read_stdout_line(self, deadline): 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._read(deadline, self._pop_stdout_line_if_ready) 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def read_stderr_line(self, deadline): 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._read(deadline, self._pop_stderr_line_if_ready) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def read_either_stdout_or_stderr_line(self, deadline): 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def retrieve_bytes_from_buffers(): 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stdout_line = self._pop_stdout_line_if_ready() 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if stdout_line: 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return stdout_line, None 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stderr_line = self._pop_stderr_line_if_ready() 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if stderr_line: 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None, stderr_line 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None # Instructs the caller to keep waiting. 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return_value = self._read(deadline, retrieve_bytes_from_buffers) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # FIXME: This is a bit of a hack around the fact that _read normally only returns one value, but this caller wants it to return two. 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if return_value is None: 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None, None 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return return_value 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def read_stdout(self, deadline, size): 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if size <= 0: 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise ValueError('ServerProcess.read() called with a non-positive size: %d ' % size) 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def retrieve_bytes_from_stdout_buffer(): 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if len(self._output) >= size: 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._pop_output_bytes(size) 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._read(deadline, retrieve_bytes_from_stdout_buffer) 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _log(self, message): 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # This is a bit of a hack, but we first log a blank line to avoid 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # messing up the master process's output. 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.info('') 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.info(message) 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 240e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) def _log_data(self, prefix, data): 241e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if self._logging and data and len(data): 242e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) for line in quote_data(data): 243e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) _log.info('%s: %s', prefix, line) 244e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _handle_timeout(self): 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self.timed_out = True 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._port.sample_process(self._name, self._proc.pid) 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _split_string_after_index(self, string, index): 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return string[:index], string[index:] 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _pop_output_bytes(self, bytes_count): 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) output, self._output = self._split_string_after_index(self._output, bytes_count) 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return output 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _pop_error_bytes(self, bytes_count): 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) output, self._error = self._split_string_after_index(self._error, bytes_count) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return output 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _wait_for_data_and_update_buffers_using_select(self, deadline, stopping=False): 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.stdout.closed or self._proc.stderr.closed: 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # If the process crashed and is using FIFOs, like Chromium Android, the 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # stdout and stderr pipes will be closed. 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) out_fd = self._proc.stdout.fileno() 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) err_fd = self._proc.stderr.fileno() 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) select_fds = (out_fd, err_fd) 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try: 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) read_fds, _, _ = select.select(select_fds, [], select_fds, max(deadline - time.time(), 0)) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) except select.error, e: 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # We can ignore EINVAL since it's likely the process just crashed and we'll 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # figure that out the next time through the loop in _read(). 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if e.args[0] == errno.EINVAL: 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try: 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Note that we may get no data during read() even though 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # select says we got something; see the select() man page 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # on linux. I don't know if this happens on Mac OS and 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # other Unixen as well, but we don't bother special-casing 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Linux because it's relatively harmless either way. 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if out_fd in read_fds: 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) data = self._proc.stdout.read() 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not data and not stopping and (self._treat_no_data_as_crash or self._proc.poll()): 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._crashed = True 288e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) self._log_data('OUT', data) 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._output += data 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if err_fd in read_fds: 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) data = self._proc.stderr.read() 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not data and not stopping and (self._treat_no_data_as_crash or self._proc.poll()): 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._crashed = True 295e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) self._log_data('ERR', data) 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._error += data 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) except IOError, e: 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # We can ignore the IOErrors because we will detect if the subporcess crashed 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # the next time through the loop in _read() 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pass 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _wait_for_data_and_update_buffers_using_win32_apis(self, deadline): 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # See http://code.activestate.com/recipes/440554-module-to-allow-asynchronous-subprocess-use-on-win/ 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # and http://docs.activestate.com/activepython/2.6/pywin32/modules.html 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # for documentation on all of these win32-specific modules. 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) now = time.time() 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) out_fh = msvcrt.get_osfhandle(self._proc.stdout.fileno()) 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) err_fh = msvcrt.get_osfhandle(self._proc.stderr.fileno()) 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (self._proc.poll() is None) and (now < deadline): 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) output = self._non_blocking_read_win32(out_fh) 311e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) self._log_data('OUT', output) 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) error = self._non_blocking_read_win32(err_fh) 313e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) self._log_data('ERR', error) 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if output or error: 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if output: 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._output += output 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if error: 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._error += error 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) time.sleep(0.01) 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) now = time.time() 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _non_blocking_read_win32(self, handle): 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try: 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _, avail, _ = win32pipe.PeekNamedPipe(handle, 0) 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if avail > 0: 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _, buf = win32file.ReadFile(handle, avail, None) 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return buf 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) except Exception, e: 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if e[0] not in (109, errno.ESHUTDOWN): # 109 == win32 ERROR_BROKEN_PIPE 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def has_crashed(self): 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not self._crashed and self.poll(): 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._crashed = True 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._handle_possible_interrupt() 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self._crashed 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # This read function is a bit oddly-designed, as it polls both stdout and stderr, yet 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # only reads/returns from one of them (buffering both in local self._output/self._error). 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # It might be cleaner to pass in the file descriptor to poll instead. 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _read(self, deadline, fetch_bytes_from_buffers_callback): 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while True: 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self.has_crashed(): 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if time.time() > deadline: 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._handle_timeout() 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return None 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bytes = fetch_bytes_from_buffers_callback() 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if bytes is not None: 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return bytes 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._use_win32_apis: 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._wait_for_data_and_update_buffers_using_win32_apis(deadline) 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else: 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._wait_for_data_and_update_buffers_using_select(deadline) 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def start(self): 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not self._proc: 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._start() 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) def stop(self, timeout_secs=0.0): 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not self._proc: 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (None, None) 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) now = time.time() 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.stdin: 372e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if self._logging: 373e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) _log.info(' IN: ^D') 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdin.close() 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdin = None 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) killed = False 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if timeout_secs: 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deadline = now + timeout_secs 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while self._proc.poll() is None and time.time() < deadline: 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) time.sleep(0.01) 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.poll() is None: 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.warning('stopping %s(pid %d) timed out, killing it' % (self._name, self._proc.pid)) 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.poll() is None: 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._kill() 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) killed = True 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.debug('killed pid %d' % self._proc.pid) 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # read any remaining data on the pipes and return it. 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not killed: 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._use_win32_apis: 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._wait_for_data_and_update_buffers_using_win32_apis(now) 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else: 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._wait_for_data_and_update_buffers_using_select(now, stopping=True) 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) out, err = self._output, self._error 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._reset() 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (out, err) 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def kill(self): 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self.stop(0.0) 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _kill(self): 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._host.executive.kill_process(self._proc.pid) 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._proc.poll() is not None: 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.wait() 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def replace_outputs(self, stdout, stderr): 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) assert self._proc 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if stdout: 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdout.close() 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stdout = stdout 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if stderr: 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stderr.close() 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._proc.stderr = stderr 415