blob: d535b5fe1c38b9aac06e7c46553f8d30929e18af [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (C) 2010 Apple Inc. All rights reserved.
# Copyright (C) 2011 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from __future__ import print_function
import json
import os
import getpass
import re
import subprocess
import sys
import time
def listAllWebKitPrograms(builddir_bin):
foundWebKitPrograms = []
for root, dirs, files in os.walk(builddir_bin):
for file in files:
if os.access(os.path.join(root, file), os.X_OK):
foundWebKitPrograms.append(file)
return foundWebKitPrograms
def removeOrphanShmSegments():
# When Apache2 is not gracefully shut down, it may leave orphaned shared memory segments
# that could cause following server instances to abort on startup.
try:
username = getpass.getuser()
segments = orphanedShmSegmentsByUser(username)
for s in segments:
subprocess.check_call(["ipcrm", "-m", s])
except Exception as e:
print("Error removing orphaned shared memory segments: {}".format(e), file=sys.stderr)
def orphanedShmSegmentsByUser(username):
ret = []
output = subprocess.check_output(["ipcs", "-m"])
if type(output) == bytes:
output = output.decode('utf-8', errors='strict')
lines = output.split('\n')
if len(lines) < 3:
return []
headers = [header.strip() for header in lines[2].split()]
wanted_headers = ['nattch', 'owner', 'shmid']
if any(h not in headers for h in wanted_headers):
raise RuntimeError("Failed to find required nattch, owner and shmid cols in ipcs output")
nattch_idx = headers.index('nattch')
owner_idx = headers.index('owner')
shmid_idx = headers.index('shmid')
for line in lines[3:]:
line = line.strip()
tokens = [x.strip() for x in line.split()]
try:
if tokens[nattch_idx] == '0' and tokens[owner_idx] == username:
ret.append(tokens[shmid_idx])
except IndexError:
continue
return ret
def are_simulators_booted():
simctl_output = dict()
try:
simctl_output = json.loads(subprocess.check_output(
['xcrun', 'simctl', 'list', '--json'],
**(dict(encoding='utf-8') if sys.version_info > (3, 0) else dict())
))
except json.decoder.JSONDecodeError:
return False
for runtime, devices in simctl_output.get('devices', {}).items():
for device in devices:
state = device.get('state', '(unavailable)')
if state not in ('(unavailable)', 'Shutdown'):
print('{} is still {}'.format(device.get('udid', '?'), state))
return True
return False
def main(user=None):
tasksToKillWin = [
"cl.exe",
"devenv.com",
"devenv.exe",
"DumpRenderTree.exe",
"DumpRenderTree_debug.exe",
"httpd.exe",
"imagediff.exe",
"imagediff_debug.exe",
"jsc.exe",
"jsc_debug.exe",
"LightTPD.exe",
"link.exe",
"midl.exe",
"perl.exe",
"Safari.exe",
"svn.exe",
"testapi.exe",
"testapi_debug.exe",
"VcBuildHelper.exe",
"wdiff.exe",
"WebKitNetworkProcess.exe",
"WebKitNetworkProcess_debug.exe",
"WebKitWebProcess.exe",
"WebKitWebProcess_debug.exe",
"WebKitTestRunner.exe",
"WebKitTestRunner_debug.exe",
]
tasksToKillMac = [
"apache2",
"cc1plus",
"cc1objplus",
"clang",
r"clang\\+\\+",
"gcc-4.2",
"httpd",
"i686-apple-darwin10-gcc-4.2.1",
"ImageDiff",
"jsc",
"LayoutTestHelper",
"make",
"perl5.12",
"perl5.16",
"perl5.18",
"perl5.30",
"perl",
"Problem Reporter",
"ruby",
"Safari Web Content",
"Safari",
"svn",
"DumpRenderTree",
"TestWebKitAPI Web Content",
"TestWebKitAPI",
"PluginProcess",
"com.apple.WebKit.Plugin.64",
"com.apple.WebKit.Plugin.32",
"com.apple.WebKit.PluginProcess",
"com.apple.WebKit.PluginProcess.Development"
"WebKitTestRunner Web Content",
"WebKitTestRunner",
"WebProcess",
"xcodebuild",
# FIXME: Consider moving iOS-specific tasks to their own list.
"Simulator",
]
taskToKillUnix = [
# System process that are executed as part of the build process
"cc1plus",
"ld.gold",
"ld",
"make",
"cmake",
"svn",
# System process that are executed as part of the test steps
"Xvfb",
"gdb",
"ruby",
"apache2",
"httpd",
# WebKit related process names are automatically generated for GTK+/WPE/JSCOnly
]
# This allows to specify on the environment of the bot a list of process that should be killed.
tasksToKill = os.getenv("WEBKITBOT_TASKSTOKILL", "").split()
if sys.platform == 'darwin':
# Shutdown any simulators
if os.geteuid() == 0 and user:
os.system("sudo -u {} xcrun simctl shutdown all".format(user))
else:
os.system("xcrun simctl shutdown all")
# Ensure that simulators are shut down
start = time.time()
while are_simulators_booted() and start + 60 > time.time():
print('Waiting on simulators to shut down...')
time.sleep(10)
os.system("ps aux")
for task in tasksToKill + tasksToKillMac:
os.system("killall -9 -v -m " + task)
# Kill all instances of python executing run-webkit-tests
os.system("ps aux | grep -E '.+/Python3? .+(run_webkit_tests|run-webkit-tests|mod_pywebsocket)' | grep -v grep | awk '{print $2}' | xargs kill")
# FIXME: <rdar://problem/81476546> Remove stale simulator temp files
# Hard-code path because when run with 'sudo,' this script doesn't get the right tempfile location
os.system('find /var/folders -name "Deleting-*" -maxdepth 4 -exec sudo rm -rf {} +')
elif sys.platform == 'cygwin' or sys.platform == 'win32':
for task in tasksToKill + tasksToKillWin:
os.system("taskkill /t /f /im " + task)
elif sys.platform.startswith('linux'):
os.system("ps aux")
builddir_bin = "WebKitBuild/Release/bin" if os.path.isdir("WebKitBuild/Release/bin") else "WebKitBuild/Debug/bin"
for task in tasksToKill + taskToKillUnix + listAllWebKitPrograms(builddir_bin):
os.system("killall -9 -v " + task)
os.system("ps aux | grep -P '.+/python3? .+(run_webkit_tests|run-webkit-tests|mod_pywebsocket)' | grep -v grep | awk '{print $2}' | xargs -r kill")
removeOrphanShmSegments()
else:
sys.exit()
# FIXME: Should we return an exit code based on how the kills went?
if __name__ == '__main__':
user = sys.argv[1] if len(sys.argv) > 1 else None
sys.exit(main(user))