def KillChromeProcesses(): """Kills all the running instances of Chrome. Returns: (int) The number of processes that were killed. """ killed_count = 0 chrome_path = OPTIONS.LocalBinary('chrome') for process in psutil.process_iter(): try: process_bin_path = None # In old versions of psutil, process.exe is a member, in newer ones it's # a method. if type(process.exe) == str: process_bin_path = process.exe else: process_bin_path = process.exe() if os.path.abspath(process_bin_path) == os.path.abspath( chrome_path): process.terminate() killed_count += 1 try: process.wait(timeout=10) except psutil.TimeoutExpired: process.kill() except psutil.AccessDenied: pass except psutil.NoSuchProcess: pass return killed_count
def Open(self): """Overridden connection creation.""" # Kill all existing Chrome instances. killed_count = LocalChromeController.KillChromeProcesses() if killed_count > 0: logging.warning('Killed existing Chrome instance.') chrome_cmd = [OPTIONS.LocalBinary('chrome')] chrome_cmd.extend(self._GetChromeArguments()) # Force use of simple cache. chrome_cmd.append('--use-simple-cache-backend=on') chrome_cmd.append('--user-data-dir=%s' % self._profile_dir) # Navigates to about:blank for couples of reasons: # - To find the correct target descriptor at devtool connection; # - To avoid cache and WPR pollution by the NTP. chrome_cmd.append('about:blank') tmp_log = \ tempfile.NamedTemporaryFile(prefix="chrome_controller_", suffix='.log') chrome_process = None try: chrome_env_override = self._chrome_env_override.copy() if self._wpr_attributes: chrome_env_override.update( self._wpr_attributes.chrome_env_override) chrome_env = os.environ.copy() chrome_env.update(chrome_env_override) # Launch Chrome. logging.info( common_util.GetCommandLineForLogging(chrome_cmd, chrome_env_override)) chrome_process = subprocess.Popen(chrome_cmd, stdout=tmp_log.file, stderr=tmp_log.file, env=chrome_env) # Attempt to connect to Chrome's devtools for attempt_id in xrange(self.DEVTOOLS_CONNECTION_ATTEMPTS): logging.info('Devtools connection attempt %d' % attempt_id) process_result = chrome_process.poll() if process_result is not None: raise ChromeControllerInternalError( 'Unexpected Chrome exit: {}'.format(process_result)) try: connection = devtools_monitor.DevToolsConnection( OPTIONS.devtools_hostname, OPTIONS.devtools_port) break except socket.error as e: if e.errno != errno.ECONNREFUSED: raise time.sleep( self.DEVTOOLS_CONNECTION_ATTEMPT_INTERVAL_SECONDS) else: raise ChromeControllerInternalError( 'Failed to connect to Chrome devtools after {} ' 'attempts.'.format(self.DEVTOOLS_CONNECTION_ATTEMPTS)) # Start and yield the devtool connection. self._StartConnection(connection) yield connection if self._slow_death: connection.Close() chrome_process.wait() chrome_process = None except ChromeControllerError._PASSTHROUGH_WHITE_LIST: raise except Exception: raise ChromeControllerError(log=open(tmp_log.name).read()) finally: if OPTIONS.local_noisy: sys.stderr.write(open(tmp_log.name).read()) del tmp_log if chrome_process: try: chrome_process.kill() except OSError: pass # Chrome is already dead.