Author: Charles Zablit Date: 2026-08-11T14:38:01+02:00 New Revision: 870e6890821e6f95dbc1bde35922b73a97e5d169
URL: https://github.com/llvm/llvm-project/commit/870e6890821e6f95dbc1bde35922b73a97e5d169 DIFF: https://github.com/llvm/llvm-project/commit/870e6890821e6f95dbc1bde35922b73a97e5d169.diff LOG: [lldb][Windows] Dump thread stacks before lit's timeout kills a test (#213239) On Windows, when a test hits a timeout, we currently don't get a stacktrace. dotest solves this on POSIX: it registers a SIGTERM handler, so a killed test prints its stack. The handler does not run on Windows however because `faulthandler.register` doesn't exist there, and lit terminates the process instead of signalling it (no signals on Windows). This patch adds `faulthandler.dump_traceback_later()` with a default timeout value of 300s. That's longer than the longest test in CI (~150s) and does not kill the test. It simply dumps the stacktrace at a point where the test is very likely stuck. # Before ``` TIMEOUT: lldb-api :: types/TestFloatTypesExpr.py (2698 of 2698) ******************** TEST 'lldb-api :: types/TestFloatTypesExpr.py' FAILED ******************** Exit Code: 15 Timeout: Reached timeout of 900 seconds ``` There is no stacktrace. # After ``` Timeout (0:00:20)! Thread 0x00012fe8 (most recent call first): File ".../types/TestFloatTypesExpr.py", line 22 in test_float_type File ".../lldbsuite/test/lldbtest.py", line 2097 in test_method File ".../unittest/case.py", line 549 in _callTestMethod ... File ".../lldbsuite/test/dotest.py", line 1212 in run_suite ``` Added: Modified: lldb/packages/Python/lldbsuite/test/configuration.py lldb/packages/Python/lldbsuite/test/dotest.py lldb/packages/Python/lldbsuite/test/dotest_args.py lldb/test/API/lldbtest.py Removed: ################################################################################ diff --git a/lldb/packages/Python/lldbsuite/test/configuration.py b/lldb/packages/Python/lldbsuite/test/configuration.py index 7f9616be9a482..af069adf9c69e 100644 --- a/lldb/packages/Python/lldbsuite/test/configuration.py +++ b/lldb/packages/Python/lldbsuite/test/configuration.py @@ -169,6 +169,10 @@ # Typical values include Debug, Release, RelWithDebInfo and MinSizeRel cmake_build_type = None +# The timeout (in seconds) lit is using to run this test, if any. 0 means no +# timeout was configured. +timeout = 0 + def shouldSkipBecauseOfCategories(test_categories): if use_categories: diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 2bd1d085f6ceb..01863c4eab2b0 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -449,6 +449,8 @@ def parseOptionsAndInitTestdirs(): configuration.lldb_platform_available_ports = args.lldb_platform_available_ports if platform_system == "Darwin" and args.apple_sdk: configuration.apple_sdk = args.apple_sdk + if args.timeout: + configuration.timeout = args.timeout if args.test_build_dir: configuration.test_build_dir = args.test_build_dir if args.lldb_module_cache_dir: @@ -504,6 +506,17 @@ def registerFaulthandler(): if getattr(faulthandler, "register", None): faulthandler.register(signal.SIGTERM, chain=True) + if sys.platform != "win32": + return + + # Dump every thread's stack shortly before lit's own per-test timeout would + # kill the process. + if configuration.timeout <= 0: + return + + secs = max(1.0, configuration.timeout * 0.9) + faulthandler.dump_traceback_later(secs, exit=False) + def setupSysPath(): """ diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py index 41070edf89022..516559fb6268d 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest_args.py +++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py @@ -248,6 +248,14 @@ def create_parser(): ), help="The root build directory for the tests. It will be removed before running.", ) + group.add_argument( + "--timeout", + dest="timeout", + metavar="Timeout in seconds", + type=float, + default=0, + help="The timeout lit is using to run this test, if any.", + ) group.add_argument( "--lldb-module-cache-dir", dest="lldb_module_cache_dir", diff --git a/lldb/test/API/lldbtest.py b/lldb/test/API/lldbtest.py index 62952b67bb64f..571b2157542de 100644 --- a/lldb/test/API/lldbtest.py +++ b/lldb/test/API/lldbtest.py @@ -55,6 +55,9 @@ def execute(self, test, litConfig): # python exe as the first parameter of the command. cmd = [executable] + self.dotest_cmd + [testPath, "-p", testFile] + if test.config.maxIndividualTestTime > 0: + cmd += ["--timeout", str(test.config.maxIndividualTestTime)] + launcher = getattr(test.config, "lldb_launcher", None) if launcher: cmd = [launcher] + cmd _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
