15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2011 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 name of Google Inc. 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) 2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)"""Base class used to start servers used by the layout tests.""" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import errno 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import logging 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import socket 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import tempfile 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import time 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)_log = logging.getLogger(__name__) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class ServerError(Exception): 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pass 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class ServerBase(object): 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """A skeleton class for starting and stopping servers used by the layout tests.""" 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) def __init__(self, port_obj, output_dir): 4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._port_obj = port_obj 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._executive = port_obj._executive 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._filesystem = port_obj._filesystem 52c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) self._platform = port_obj.host.platform 5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._output_dir = output_dir 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # We need a non-checkout-dependent place to put lock files, etc. We 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # don't use the Python default on the Mac because it defaults to a 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # randomly-generated directory under /var/folders and no one would ever 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # look there. 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tmpdir = tempfile.gettempdir() 60c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if self._platform.is_mac(): 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tmpdir = '/tmp' 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._runtime_path = self._filesystem.join(tmpdir, "WebKit") 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._filesystem.maybe_make_directory(self._runtime_path) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) # Subclasses must override these fields. 6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._name = '<virtual>' 6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._log_prefixes = tuple() 6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._mappings = {} 7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._pid_file = None 7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._start_cmd = None 7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) # Subclasses may override these fields. 7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._env = None 7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._stdout = self._executive.PIPE 7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._stderr = self._executive.PIPE 7709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._process = None 7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._pid = None 79c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) self._error_log_path = None 8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def start(self): 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """Starts the server. It is an error to start an already started server. 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) This method also stops any stale servers started by a previous instance.""" 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) assert not self._pid, '%s server is already running' % self._name 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) # Stop any stale servers left over from previous instances. 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._filesystem.exists(self._pid_file): 89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try: 90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._pid = int(self._filesystem.read_text_file(self._pid_file)) 91c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.debug('stale %s pid file, pid %d' % (self._name, self._pid)) 92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._stop_running_server() 93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) except (ValueError, UnicodeDecodeError): 94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) # These could be raised if the pid file is corrupt. 95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._remove_pid_file() 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._pid = None 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._remove_stale_logs() 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._prepare_config() 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._check_that_all_ports_are_available() 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._pid = self._spawn_process() 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if self._wait_for_action(self._is_server_running_on_all_ports): 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.debug("%s successfully started (pid = %d)" % (self._name, self._pid)) 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else: 107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) self._log_errors_from_subprocess() 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._stop_running_server() 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise ServerError('Failed to start %s server' % self._name) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def stop(self): 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """Stops the server. Stopping a server that isn't started is harmless.""" 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual_pid = None 114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try: 115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if self._filesystem.exists(self._pid_file): 116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) try: 117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) actual_pid = int(self._filesystem.read_text_file(self._pid_file)) 118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) except (ValueError, UnicodeDecodeError): 119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) # These could be raised if the pid file is corrupt. 120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) pass 121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if not self._pid: 122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._pid = actual_pid 123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if not self._pid: 125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return 126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if not actual_pid: 128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) _log.warning('Failed to stop %s: pid file is missing' % self._name) 129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return 130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if self._pid != actual_pid: 131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) _log.warning('Failed to stop %s: pid file contains %d, not %d' % 132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) (self._name, actual_pid, self._pid)) 133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) # Try to kill the existing pid, anyway, in case it got orphaned. 134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._executive.kill_process(self._pid) 135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._pid = None 136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return 137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) _log.debug("Attempting to shut down %s server at pid %d" % (self._name, self._pid)) 139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._stop_running_server() 140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) _log.debug("%s server at pid %d stopped" % (self._name, self._pid)) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._pid = None 142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) finally: 143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) # Make sure we delete the pid file no matter what happens. 144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._remove_pid_file() 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _prepare_config(self): 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """This routine can be overridden by subclasses to do any sort 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) of initialization required prior to starting the server that may fail.""" 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pass 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _remove_stale_logs(self): 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """This routine can be overridden by subclasses to try and remove logs 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left over from a prior run. This routine should log warnings if the 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) files cannot be deleted, but should not fail unless failure to 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delete the logs will actually cause start() to fail.""" 15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) # Sometimes logs are open in other processes but they should clear eventually. 15709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for log_prefix in self._log_prefixes: 15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) try: 15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._remove_log_files(self._output_dir, log_prefix) 16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) except OSError, e: 16109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) _log.warning('Failed to remove old %s %s files' % (self._name, log_prefix)) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _spawn_process(self): 16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) _log.debug('Starting %s server, cmd="%s"' % (self._name, self._start_cmd)) 16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) process = self._executive.popen(self._start_cmd, env=self._env, stdout=self._stdout, stderr=self._stderr) 16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) pid = process.pid 16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._filesystem.write_text_file(self._pid_file, str(pid)) 16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return pid 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _stop_running_server(self): 17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._wait_for_action(self._check_and_kill) 17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if self._filesystem.exists(self._pid_file): 17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._filesystem.remove(self._pid_file) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) def _check_and_kill(self): 17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if self._executive.check_running_pid(self._pid): 177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.debug('pid %d is running, killing it' % self._pid) 17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) host = self._port_obj.host 17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) self._executive.kill_process(self._pid) 18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return False 181c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) else: 182c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.debug('pid %d is not running' % self._pid) 183c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 18409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return True 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) def _remove_pid_file(self): 187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if self._filesystem.exists(self._pid_file): 188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) self._filesystem.remove(self._pid_file) 189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _remove_log_files(self, folder, starts_with): 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) files = self._filesystem.listdir(folder) 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for file in files: 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if file.startswith(starts_with): 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) full_path = self._filesystem.join(folder, file) 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self._filesystem.remove(full_path) 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 197c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) def _log_errors_from_subprocess(self): 198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('logging %s errors, if any' % self._name) 199c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if self._process: 200c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s returncode %s' % (self._name, str(self._process.returncode))) 201c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if self._process.stderr: 202c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) stderr_text = self._process.stderr.read() 203c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if stderr_text: 204c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s stderr:' % self._name) 205c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) for line in stderr_text.splitlines(): 206c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error(' %s' % line) 207c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) else: 208c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s no stderr' % self._name) 209c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) else: 210c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s no stderr handle' % self._name) 211c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) else: 212c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s no process' % self._name) 213c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if self._error_log_path and self._filesystem.exists(self._error_log_path): 214c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) error_log_text = self._filesystem.read_text_file(self._error_log_path) 215c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if error_log_text: 216c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s error log (%s) contents:' % (self._name, self._error_log_path)) 217c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) for line in error_log_text.splitlines(): 218c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error(' %s' % line) 219c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) else: 220c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s error log empty' % self._name) 221c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('') 222c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) else: 223c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.error('%s no error log' % self._name) 224c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _wait_for_action(self, action, wait_secs=20.0, sleep_secs=1.0): 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """Repeat the action for wait_sec or until it succeeds, sleeping for sleep_secs 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) in between each attempt. Returns whether it succeeded.""" 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) start_time = time.time() 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while time.time() - start_time < wait_secs: 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if action(): 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return True 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.debug("Waiting for action: %s" % action) 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) time.sleep(sleep_secs) 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return False 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _is_server_running_on_all_ports(self): 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) """Returns whether the server is running on all the desired ports.""" 239c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 240c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) # TODO(dpranke): crbug/378444 maybe pid is unreliable on win? 241c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if not self._platform.is_win() and not self._executive.check_running_pid(self._pid): 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.debug("Server isn't running at all") 243c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) self._log_errors_from_subprocess() 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise ServerError("Server exited") 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for mapping in self._mappings: 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s = socket.socket() 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) port = mapping['port'] 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try: 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s.connect(('localhost', port)) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.debug("Server running on %d" % port) 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) except IOError, e: 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if e.errno not in (errno.ECONNREFUSED, errno.ECONNRESET): 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _log.debug("Server NOT running on %d: %s" % (port, e)) 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return False 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) finally: 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s.close() 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return True 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) def _check_that_all_ports_are_available(self): 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for mapping in self._mappings: 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s = socket.socket() 264e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if not self._platform.is_win(): 265e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) port = mapping['port'] 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) try: 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s.bind(('localhost', port)) 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) except IOError, e: 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if e.errno in (errno.EALREADY, errno.EADDRINUSE): 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise ServerError('Port %d is already in use.' % port) 272c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) elif self._platform.is_win() and e.errno in (errno.WSAEACCES,): # pylint: disable=E1101 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise ServerError('Port %d is already in use.' % port) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else: 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raise 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) finally: 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s.close() 278c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) _log.debug('all ports are available') 279