Commit b6b5a980 authored by chrisgao@chromium.org's avatar chrisgao@chromium.org

[telemetry] Kill IE processes when CTRL+C.

CTRL+C will make IEDriverServer exits and leaves IE running.
During cleanup, kill the IE processes when needed.

BUG=282480

Review URL: https://chromiumcodereview.appspot.com/23572025

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221606 0039d316-1c4b-4281-b951-d872f2087c98
parent 6b2d4a0b
...@@ -45,7 +45,7 @@ class WebDriverBrowserBackend(browser_backend.BrowserBackend): ...@@ -45,7 +45,7 @@ class WebDriverBrowserBackend(browser_backend.BrowserBackend):
# webdriver API. # webdriver API.
return False return False
def GetProcessName(self, _): def GetProcessName(self, cmd_line):
# Leave implementation details to subclass as process name depends on the # Leave implementation details to subclass as process name depends on the
# type of browser. # type of browser.
raise NotImplementedError() raise NotImplementedError()
...@@ -62,9 +62,5 @@ class WebDriverBrowserBackend(browser_backend.BrowserBackend): ...@@ -62,9 +62,5 @@ class WebDriverBrowserBackend(browser_backend.BrowserBackend):
# Assume the browser is running if not explicitly closed. # Assume the browser is running if not explicitly closed.
return self._driver is not None return self._driver is not None
def GetStandardOutput(self):
# TODO(chrisgao): check if python client can get stdout of browsers.
return ''
def __del__(self): def __del__(self):
self.Close() self.Close()
...@@ -11,7 +11,7 @@ from telemetry.core import browser ...@@ -11,7 +11,7 @@ from telemetry.core import browser
from telemetry.core import possible_browser from telemetry.core import possible_browser
from telemetry.core import platform from telemetry.core import platform
from telemetry.core import util from telemetry.core import util
from telemetry.core.backends.webdriver import webdriver_browser_backend from telemetry.core.backends.webdriver import webdriver_ie_backend
from telemetry.page import cloud_storage from telemetry.page import cloud_storage
# Try to import the selenium python lib which may be not available. # Try to import the selenium python lib which may be not available.
...@@ -39,12 +39,13 @@ class PossibleWebDriverBrowser(possible_browser.PossibleBrowser): ...@@ -39,12 +39,13 @@ class PossibleWebDriverBrowser(possible_browser.PossibleBrowser):
def __init__(self, browser_type, finder_options): def __init__(self, browser_type, finder_options):
super(PossibleWebDriverBrowser, self).__init__(browser_type, finder_options) super(PossibleWebDriverBrowser, self).__init__(browser_type, finder_options)
def CreateWebDriverBackend(self): def CreateWebDriverBackend(self, platform_backend):
raise NotImplementedError() raise NotImplementedError()
def Create(self): def Create(self):
backend = self.CreateWebDriverBackend() platform_backend = platform.CreatePlatformBackendForCurrentOS()
b = browser.Browser(backend, platform.CreatePlatformBackendForCurrentOS()) backend = self.CreateWebDriverBackend(platform_backend)
b = browser.Browser(backend, platform_backend)
return b return b
def SupportsOptions(self, finder_options): def SupportsOptions(self, finder_options):
...@@ -61,7 +62,7 @@ class PossibleDesktopIE(PossibleWebDriverBrowser): ...@@ -61,7 +62,7 @@ class PossibleDesktopIE(PossibleWebDriverBrowser):
super(PossibleDesktopIE, self).__init__(browser_type, finder_options) super(PossibleDesktopIE, self).__init__(browser_type, finder_options)
self._architecture = architecture self._architecture = architecture
def CreateWebDriverBackend(self): def CreateWebDriverBackend(self, platform_backend):
assert webdriver assert webdriver
def DriverCreator(): def DriverCreator():
ie_driver_exe = os.path.join(util.GetTelemetryDir(), 'bin', ie_driver_exe = os.path.join(util.GetTelemetryDir(), 'bin',
...@@ -69,8 +70,8 @@ class PossibleDesktopIE(PossibleWebDriverBrowser): ...@@ -69,8 +70,8 @@ class PossibleDesktopIE(PossibleWebDriverBrowser):
cloud_storage.GetIfChanged(cloud_storage.CHROMIUM_TELEMETRY_BUCKET, cloud_storage.GetIfChanged(cloud_storage.CHROMIUM_TELEMETRY_BUCKET,
ie_driver_exe) ie_driver_exe)
return webdriver.Ie(executable_path=ie_driver_exe) return webdriver.Ie(executable_path=ie_driver_exe)
return webdriver_browser_backend.WebDriverBrowserBackend( return webdriver_ie_backend.WebDriverIEBackend(
DriverCreator, False, self.finder_options) platform_backend, DriverCreator, self.finder_options)
def SelectDefaultBrowser(_): def SelectDefaultBrowser(_):
return None return None
......
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import re
import urllib2
from telemetry.core.backends.webdriver import webdriver_browser_backend
class WebDriverIEBackend(webdriver_browser_backend.WebDriverBrowserBackend):
# For unsupported functions. pylint: disable=W0223
def __init__(self, platform_backend, driver_creator, options):
super(WebDriverIEBackend, self).__init__(
driver_creator=driver_creator,
supports_extensions=False,
options=options)
self._platform_backend = platform_backend
def GetProcessName(self, cmd_line):
if re.search('SCODEF:\d+ CREDAT:\d+', cmd_line, re.IGNORECASE):
return 'Content'
else:
return 'Manager'
@property
def pid(self):
for pi in self._platform_backend.GetSystemProcessInfo():
if (pi['ParentProcessId'] == self.driver.iedriver.process.pid and
pi['Name'].lower() == 'iexplore.exe'):
return pi['ProcessId']
return None
def Close(self):
try:
super(WebDriverIEBackend, self).Close()
except urllib2.URLError:
# CTRL + C makes IEDriverServer exits while leaving IE still running.
for pi in self._platform_backend.GetSystemProcessInfo():
if (pi['ParentProcessId'] == self.driver.iedriver.process.pid):
self._platform_backend.KillProcess(pi['ProcessId'], True)
def IsBrowserRunning(self):
return self.pid is not None
...@@ -100,22 +100,46 @@ class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend): ...@@ -100,22 +100,46 @@ class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend):
'ReadTransferCount': io_stats['ReadTransferCount'], 'ReadTransferCount': io_stats['ReadTransferCount'],
'WriteTransferCount': io_stats['WriteTransferCount']} 'WriteTransferCount': io_stats['WriteTransferCount']}
def KillProcess(self, pid, kill_process_tree=False):
# os.kill for Windows is Python 2.7.
cmd = ['taskkill', '/F', '/PID', str(pid)]
if kill_process_tree:
cmd.append('/T')
subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT).wait()
def GetSystemProcessInfo(self):
# [3:] To skip 2 blank lines and header.
lines = subprocess.Popen(
['wmic', 'process', 'get',
'CommandLine,CreationDate,Name,ParentProcessId,ProcessId',
'/format:csv'],
stdout=subprocess.PIPE).communicate()[0].splitlines()[3:]
process_info = []
for line in lines:
if not line:
continue
parts = line.split(',')
pi = {}
pi['ProcessId'] = int(parts[-1])
pi['ParentProcessId'] = int(parts[-2])
pi['Name'] = parts[-3]
creation_date = None
if parts[-4]:
creation_date = float(re.split('[+-]', parts[-4])[0])
pi['CreationDate'] = creation_date
pi['CommandLine'] = ','.join(parts[1:-4])
process_info.append(pi)
return process_info
def GetChildPids(self, pid): def GetChildPids(self, pid):
"""Retunds a list of child pids of |pid|.""" """Retunds a list of child pids of |pid|."""
creation_ppid_pid_list = subprocess.Popen(
['wmic', 'process', 'get', 'CreationDate,ParentProcessId,ProcessId',
'/format:csv'],
stdout=subprocess.PIPE).communicate()[0]
ppid_map = collections.defaultdict(list) ppid_map = collections.defaultdict(list)
creation_map = {} creation_map = {}
# [3:] To skip 2 blank lines and header. for pi in self.GetSystemProcessInfo():
for creation_ppid_pid in creation_ppid_pid_list.splitlines()[3:]: ppid_map[pi['ParentProcessId']].append(pi['ProcessId'])
if not creation_ppid_pid: if pi['CreationDate']:
continue creation_map[pi['ProcessId']] = pi['CreationDate']
_, creation, curr_ppid, curr_pid = creation_ppid_pid.split(',')
ppid_map[int(curr_ppid)].append(int(curr_pid))
if creation:
creation_map[int(curr_pid)] = float(re.split('[+-]', creation)[0])
def _InnerGetChildPids(pid): def _InnerGetChildPids(pid):
if not pid or pid not in ppid_map: if not pid or pid not in ppid_map:
...@@ -130,19 +154,9 @@ class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend): ...@@ -130,19 +154,9 @@ class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend):
return _InnerGetChildPids(pid) return _InnerGetChildPids(pid)
def GetCommandLine(self, pid): def GetCommandLine(self, pid):
command_pid_list = subprocess.Popen( for pi in self.GetSystemProcessInfo():
['wmic', 'process', 'get', 'CommandLine,ProcessId', if pid == pi['ProcessId']:
'/format:csv'], return pi['CommandLine']
stdout=subprocess.PIPE).communicate()[0]
# [3:] To skip 2 blank lines and header.
for command_pid in command_pid_list.splitlines()[3:]:
if not command_pid:
continue
parts = command_pid.split(',')
curr_pid = parts[-1]
if pid == int(curr_pid):
command = ','.join(parts[1:-1])
return command
raise Exception('Could not get command line for %d' % pid) raise Exception('Could not get command line for %d' % pid)
def GetOSName(self): def GetOSName(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment