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