# Copyright (C) 2013 University of Szeged
# This module is a refactoring from gtk.py, Copyright (C) 2013 Igalia S.L
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * 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.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
# OWNER OR 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.

import datetime
import os
import re
import shutil
import subprocess
import tempfile
import time

from webkitpy.common.system.executive import ScriptError
from webkitpy.common.unicode_compatibility import decode_if_necessary


class GDBCrashLogGenerator(object):
    _find_pid_regex = re.compile(r'PID: (\d+) \(.*\)')

    def __init__(self, executive, name, pid, newer_than, filesystem, path_to_driver):
        self.name = name
        self.pid = pid
        self.newer_than = newer_than
        self._filesystem = filesystem
        self._path_to_driver = path_to_driver
        self._executive = executive

    def _get_gdb_output(self, coredump_path):
        process_name = self._filesystem.join(os.path.dirname(str(self._path_to_driver())), self.name)
        cmd = ['gdb', '-ex', 'thread apply all bt 1024', '--batch', process_name, coredump_path]
        proc = self._executive.popen(cmd, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = proc.communicate()
        errors = [stderr_line.strip().decode('utf8', 'ignore') for stderr_line in stderr.splitlines()]
        if proc.returncode != 0:
            stdout = ('ERROR: The gdb process exited with non-zero return code %s\n\n' % proc.returncode) + stdout
        return (stdout.decode('utf8', 'ignore'), errors)

    def _get_tmp_file_name(self, coredumpctl, filename):
        if coredumpctl[0] == 'flatpak-spawn':
            return "/run/host/" + filename

        return filename

    def _get_trace_from_systemd(self, coredumpctl, pid):
        # Letting up to 5 seconds for the backtrace to be generated on the systemd side
        for try_number in range(5):
            if try_number != 0:
                # Looping, it means we consider the logs might not be ready yet.
                time.sleep(1)

            try:
                info = self._executive.run_command(coredumpctl + ['info', "--since=" + time.strftime("%a %Y-%m-%d %H:%M:%S %Z", time.localtime(self.newer_than))],
                    return_stderr=True)
            except (ScriptError, OSError):
                continue

            found_newer = False
            # Coredumpctl will use the latest core dump with the specified PID
            # assume it is the right one.
            pids = self._find_pid_regex.findall(info)
            if not pids:
                continue

            pid = pids[0]
            with tempfile.NamedTemporaryFile() as temp_file:
                if self._executive.run_command(coredumpctl + ['dump', pid, '--output',
                        temp_file.name], return_exit_code=True):
                    continue

                res = self._get_gdb_output(self._get_tmp_file_name(coredumpctl, temp_file.name))

                return res

        return '', []

    def generate_crash_log(self, stdout, stderr):
        pid_representation = str(self.pid or '<unknown>')
        log_directory = os.environ.get("WEBKIT_CORE_DUMPS_DIRECTORY")
        errors = []
        crash_log = ''
        expected_crash_dump_filename = "core-pid_%s.dump" % pid_representation
        proc_name = "%s" % (self.name)

        def match_filename(filesystem, directory, filename):
            if self.pid:
                return filename == expected_crash_dump_filename
            return filename.find(self.name) > -1

        # Poor man which, ignore any failure.
        for coredumpctl in [['coredumpctl'], ['flatpak-spawn', '--host', 'coredumpctl'], []]:
            try:
                if not self._executive.run_command(coredumpctl, return_exit_code=True):
                    break
            except:
                continue

        if log_directory:
            dumps = self._filesystem.files_under(
                log_directory, file_filter=match_filename)
            if dumps:
                # Get the most recent coredump matching the pid and/or process name.
                coredump_path = list(reversed(sorted(dumps)))[0]
                if not self.newer_than or self._filesystem.mtime(coredump_path) > self.newer_than:
                    crash_log, errors = self._get_gdb_output(coredump_path)
        elif coredumpctl:
            crash_log, errors = self._get_trace_from_systemd(coredumpctl, pid_representation)

        stderr_lines = errors + decode_if_necessary(str(stderr or '<empty>'), errors='ignore').splitlines()
        errors_str = '\n'.join(('STDERR: ' + stderr_line) for stderr_line in stderr_lines)
        cppfilt_proc = self._executive.popen(
            ['c++filt'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        errors_str = cppfilt_proc.communicate(errors_str)[0]

        if not crash_log:
            if not log_directory:
                log_directory = "/path/to/coredumps"
            core_pattern = self._filesystem.join(log_directory, "core-pid_%p.dump")
            crash_log = """\
Coredump %(expected_crash_dump_filename)s not found. To enable crash logs:

- run this command as super-user: echo "%(core_pattern)s" > /proc/sys/kernel/core_pattern
- enable core dumps: ulimit -c unlimited
- set the WEBKIT_CORE_DUMPS_DIRECTORY environment variable: export WEBKIT_CORE_DUMPS_DIRECTORY=%(log_directory)s

""" % locals()

        return (stderr, """\
crash log for %(proc_name)s (pid %(pid_representation)s):

%(crash_log)s
%(errors_str)s""" % locals())
