Modified: trunk/Tools/ChangeLog (244063 => 244064)
--- trunk/Tools/ChangeLog 2019-04-09 01:31:54 UTC (rev 244063)
+++ trunk/Tools/ChangeLog 2019-04-09 01:32:17 UTC (rev 244064)
@@ -1,3 +1,19 @@
+2019-04-08 Jonathan Bedard <jbed...@apple.com>
+
+ Log stack-trace for run-webkit-tests when interrupted
+ https://bugs.webkit.org/show_bug.cgi?id=176393
+ <rdar://problem/34262310>
+
+ Reviewed by Lucas Forschler.
+
+ * Scripts/webkitpy/common/interrupt_debugging.py: Added.
+ (log_stack_trace): Given a Python frame object, log a stack trace to the provided file.
+ (StackTraceFileContext): Context which allows stack-traces to be printed to stderr or to a file.
+ (log_stack_trace_on_term): Attach a listener to SIGTERM so that a stack-trace can be logged when a program is terminated.
+ (log_stack_trace_on_ctrl_c): Attach a listener to SIGINT so that a stack-trace can be logged when a program is CTRL+Ced.
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+ (main): Set handlers to log stack trace on interruption.
+
2019-04-08 Fujii Hironori <hironori.fu...@sony.com>
AX: Support API: accessibilityReplaceRange:withText
Added: trunk/Tools/Scripts/webkitpy/common/interrupt_debugging.py (0 => 244064)
--- trunk/Tools/Scripts/webkitpy/common/interrupt_debugging.py (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/interrupt_debugging.py 2019-04-09 01:32:17 UTC (rev 244064)
@@ -0,0 +1,85 @@
+# Copyright (C) 2019 Apple 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 INC. 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 INC. 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.
+
+import linecache
+import logging
+import os
+import signal
+import sys
+
+_log = logging.getLogger(__name__)
+
+
+def log_stack_trace(frame, file):
+ file.write('Traceback(most recent call last):\n')
+
+ def func(frame):
+ if not frame:
+ return
+ func(frame.f_back)
+ file.write(' File "{}", line {}, in {}\n'.format(frame.f_code.co_filename, frame.f_lineno, frame.f_code.co_name))
+ file.write(' {}\n'.format(linecache.getline(frame.f_code.co_filename, frame.f_lineno).lstrip().rstrip()))
+
+ func(frame)
+
+
+class StackTraceFileContext(object):
+ def __init__(self, output_file=None):
+ self.file_name = None
+ if output_file:
+ self.file_name = os.path.join(os.path.dirname(output_file), '{}-{}'.format(os.getpid(), os.path.basename(output_file)))
+ self.file = sys.stderr
+
+ def __enter__(self):
+ if self.file_name:
+ self.file = open(self.file_name, 'w')
+ _log.critical('Stack trace saved to {}'.format(self.file_name))
+ else:
+ self.file.write('\n')
+ return self.file
+
+ def __exit__(self, *args):
+ if self.file_name:
+ self.file.close()
+ self.file = sys.stderr
+
+
+def log_stack_trace_on_term(output_file=None):
+ def handler(signum, frame):
+ with StackTraceFileContext(output_file=output_file) as file:
+ file.write('SIGTERM signal received')
+ log_stack_trace(frame, file)
+
+ exit(-1)
+
+ signal.signal(signal.SIGTERM, handler)
+
+
+def log_stack_trace_on_ctrl_c(output_file=None):
+ def handler(signum, frame):
+ with StackTraceFileContext(output_file=output_file) as file:
+ file.write('CTRL+C received\n')
+ log_stack_trace(frame, file)
+
+ raise KeyboardInterrupt
+
+ signal.signal(signal.SIGINT, handler)
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py (244063 => 244064)
--- trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py 2019-04-09 01:31:54 UTC (rev 244063)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py 2019-04-09 01:32:17 UTC (rev 244064)
@@ -1,6 +1,6 @@
# Copyright (C) 2010 Google Inc. All rights reserved.
# Copyright (C) 2010 Gabor Rapcsanyi (rga...@inf.u-szeged.hu), University of Szeged
-# Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
+# Copyright (C) 2011, 2016, 2019 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -36,6 +36,7 @@
import traceback
from webkitpy.common.host import Host
+from webkitpy.common.interrupt_debugging import log_stack_trace_on_ctrl_c, log_stack_trace_on_term
from webkitpy.layout_tests.controllers.manager import Manager
from webkitpy.layout_tests.models.test_run_results import INTERRUPTED_EXIT_STATUS
from webkitpy.port import configuration_options, platform_options
@@ -75,6 +76,10 @@
print(str(e), file=stderr)
return EXCEPTIONAL_EXIT_STATUS
+ stack_trace_path = host.filesystem.join(port.results_directory(), 'python_stack_trace.txt')
+ log_stack_trace_on_ctrl_c(output_file=stack_trace_path)
+ log_stack_trace_on_term(output_file=stack_trace_path)
+
if options.print_expectations:
return _print_expectations(port, options, args, stderr)