| #!/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)) |