Add stack trace printing to test crashes and assertions To debug rare or flaky issues that only reproduce on CI bots, install Abseil's failure signal handler centrally to print a symbolized stacktrace across Dawn and Tint test runners. Fixed: 522635660 Change-Id: I583c5c5bd501317fababf0f228811255b1dd6980 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/315996 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn index 89c39e4..4224231 100644 --- a/src/dawn/tests/BUILD.gn +++ b/src/dawn/tests/BUILD.gn
@@ -493,6 +493,7 @@ ] public_deps = [ "${dawn_root}/src/dawn/partition_alloc:raw_ptr", + "${dawn_root}/src/utils:crash_handler", "${dawn_root}/src/utils:gmock_and_gtest", ]
diff --git a/src/dawn/tests/CMakeLists.txt b/src/dawn/tests/CMakeLists.txt index 9b64d0b..cd81d38 100644 --- a/src/dawn/tests/CMakeLists.txt +++ b/src/dawn/tests/CMakeLists.txt
@@ -43,6 +43,7 @@ ) common_compile_options(dawn_test_infra) target_link_libraries(dawn_test_infra PRIVATE + dawn_crash_handler dawn_native dawn_wgpu_utils dawncpp
diff --git a/src/dawn/tests/DawnTest.cpp b/src/dawn/tests/DawnTest.cpp index f142b02..92350a1 100644 --- a/src/dawn/tests/DawnTest.cpp +++ b/src/dawn/tests/DawnTest.cpp
@@ -77,6 +77,7 @@ #include "src/dawn/utils/WGPUHelpers.h" #include "src/dawn/utils/WireHelper.h" #include "src/utils/assert.h" +#include "src/utils/crash_handler.h" #include "src/utils/log.h" #include "src/utils/platform.h" @@ -352,6 +353,7 @@ } DawnTestEnvironment::DawnTestEnvironment(int argc, char** argv) { + InstallCrashHandler(argv[0]); InitializePartitionAllocForTesting(); InitializeDanglingPointerDetectorForTesting();
diff --git a/src/dawn/tests/unittests/validation/ValidationTest.cpp b/src/dawn/tests/unittests/validation/ValidationTest.cpp index 5a09ac2..b36aa9d 100644 --- a/src/dawn/tests/unittests/validation/ValidationTest.cpp +++ b/src/dawn/tests/unittests/validation/ValidationTest.cpp
@@ -49,6 +49,7 @@ #include "src/dawn/tests/ToggleParser.h" #include "src/dawn/utils/WireHelper.h" #include "src/utils/assert.h" +#include "src/utils/crash_handler.h" namespace { @@ -61,6 +62,7 @@ } // namespace void InitDawnValidationTestEnvironment(int argc, char** argv) { + dawn::InstallCrashHandler(argv[0]); dawn::InitializePartitionAllocForTesting(); dawn::InitializeDanglingPointerDetectorForTesting();
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index 19ff862..27f27ee 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt
@@ -609,6 +609,8 @@ target_link_libraries(${TARGET} PRIVATE dawn_shared_utils) elseif(${DEPENDENCY} STREQUAL "src_utils_chromium_test_compat") target_link_libraries(${TARGET} PRIVATE dawn_shared_utils_chromium_test_compat) + elseif(${DEPENDENCY} STREQUAL "src_utils_crash_handler") + target_link_libraries(${TARGET} PRIVATE dawn_crash_handler) else() message(FATAL_ERROR "unhandled external dependency ${DEPENDENCY}") endif()
diff --git a/src/tint/cmd/test/BUILD.bazel b/src/tint/cmd/test/BUILD.bazel index fdc33fa..106768d 100644 --- a/src/tint/cmd/test/BUILD.bazel +++ b/src/tint/cmd/test/BUILD.bazel
@@ -105,6 +105,7 @@ "@gtest", "//src/utils", "//src/utils/chromium_test_compat", + "//src/utils:crash_handler", ] + select({ ":tint_build_glsl_writer": [ "//src/tint/lang/glsl/writer/common:test",
diff --git a/src/tint/cmd/test/BUILD.cmake b/src/tint/cmd/test/BUILD.cmake index 7262525..a2f7fe4 100644 --- a/src/tint/cmd/test/BUILD.cmake +++ b/src/tint/cmd/test/BUILD.cmake
@@ -105,6 +105,7 @@ "gtest" "src_utils" "src_utils_chromium_test_compat" + "src_utils_crash_handler" ) if(TINT_BUILD_GLSL_WRITER)
diff --git a/src/tint/cmd/test/BUILD.gn b/src/tint/cmd/test/BUILD.gn index eb62512..7dd570a 100644 --- a/src/tint/cmd/test/BUILD.gn +++ b/src/tint/cmd/test/BUILD.gn
@@ -49,6 +49,7 @@ sources = [ "main_test.cc" ] deps = [ "${dawn_root}/src/utils", + "${dawn_root}/src/utils:crash_handler", "${dawn_root}/src/utils/chromium_test_compat", "${tint_src_dir}:gmock_and_gtest", "${tint_src_dir}/api",
diff --git a/src/tint/cmd/test/main_test.cc b/src/tint/cmd/test/main_test.cc index 96cd3ec..d3e2b99 100644 --- a/src/tint/cmd/test/main_test.cc +++ b/src/tint/cmd/test/main_test.cc
@@ -28,9 +28,11 @@ #include "gmock/gmock.h" #include "src/tint/api/tint.h" #include "src/utils/chromium_test_compat/chromium_test_compat.h" +#include "src/utils/crash_handler.h" // Entry point for tint unit tests int main(int argc, char** argv) { + dawn::InstallCrashHandler(argv[0]); dawn::SubstituteChromiumArgs(argc, argv); testing::InitGoogleMock(&argc, argv);
diff --git a/src/tint/externals.json b/src/tint/externals.json index 32a95f8..a00b30e 100644 --- a/src/tint/externals.json +++ b/src/tint/externals.json
@@ -113,6 +113,11 @@ "libprotobuf-mutator/**" ] }, + "src_utils_crash_handler": { + "IncludePatterns": [ + "src/utils/crash_handler.*" + ] + }, "src_utils": { "IncludePatterns": [ "src/utils/*"
diff --git a/src/utils/BUILD.bazel b/src/utils/BUILD.bazel index 2a1eb14..0b35a57 100644 --- a/src/utils/BUILD.bazel +++ b/src/utils/BUILD.bazel
@@ -58,3 +58,15 @@ copts = COPTS, visibility = ["//visibility:public"], ) + +cc_library( + name = "crash_handler", + hdrs = ["crash_handler.h"], + srcs = ["crash_handler.cc"], + deps = [ + "@abseil_cpp//absl/debugging:failure_signal_handler", + "@abseil_cpp//absl/debugging:symbolize", + ], + copts = COPTS, + visibility = ["//visibility:public"], +)
diff --git a/src/utils/BUILD.gn b/src/utils/BUILD.gn index f10af3e..7a0d39e 100644 --- a/src/utils/BUILD.gn +++ b/src/utils/BUILD.gn
@@ -106,6 +106,15 @@ public_configs = [ ":internal_config" ] } +source_set("crash_handler") { + sources = [ + "crash_handler.cc", + "crash_handler.h", + ] + public_configs = [ ":internal_config" ] + deps = [ "${dawn_root}:abseil" ] +} + dawn_nocompile_source_set("nocompile_sources") { deps = [ ":utils" ] sources = [
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 444d962..bc2cc65 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt
@@ -63,3 +63,16 @@ SOURCES ${sources} ) + +dawn_add_library( + dawn_crash_handler + ENABLE_EMSCRIPTEN + UTILITY_TARGET dawn_internal_config + HEADERS + "crash_handler.h" + SOURCES + "crash_handler.cc" + DEPENDS + absl::failure_signal_handler + absl::symbolize +)
diff --git a/src/utils/assert_test.cc b/src/utils/assert_test.cc index 670bb61..6b64fce 100644 --- a/src/utils/assert_test.cc +++ b/src/utils/assert_test.cc
@@ -107,7 +107,22 @@ EXPECT_DEATH(DAWN_ASSERT(g_var2 != 124), "g_var2 != 124"); #endif } -#endif + +#ifndef _WIN32 +TEST_F(AssertDeathTest, StackTrace) { + EXPECT_DEATH(DAWN_UNREACHABLE(), "PC: @"); +} + +TEST_F(AssertDeathTest, CrashStackTrace) { + EXPECT_DEATH( + { + volatile int* ptr = nullptr; + *ptr = 1; + }, + "PC: @"); +} +#endif // !defined(_WIN32) +#endif // GTEST_HAS_DEATH_TEST using AssertFunctionalityTest = ::testing::Test;
diff --git a/src/utils/crash_handler.cc b/src/utils/crash_handler.cc new file mode 100644 index 0000000..4ab1ed9 --- /dev/null +++ b/src/utils/crash_handler.cc
@@ -0,0 +1,45 @@ +// Copyright 2026 The Dawn & Tint Authors +// +// 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. +// +// 3. Neither the name of the copyright holder 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 HOLDER 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. + +#include "src/utils/crash_handler.h" + +#include "absl/debugging/failure_signal_handler.h" +#include "absl/debugging/symbolize.h" + +namespace dawn { + +void InstallCrashHandler(const char* argv0) { + absl::InitializeSymbolizer(argv0); + absl::FailureSignalHandlerOptions options; + options.symbolize_stacktrace = true; + options.use_alternate_stack = true; + options.alarm_on_failure_secs = 3; + options.call_previous_handler = true; + absl::InstallFailureSignalHandler(options); +} + +} // namespace dawn
diff --git a/src/utils/crash_handler.h b/src/utils/crash_handler.h new file mode 100644 index 0000000..d2b7f4e0 --- /dev/null +++ b/src/utils/crash_handler.h
@@ -0,0 +1,38 @@ +// Copyright 2026 The Dawn & Tint Authors +// +// 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. +// +// 3. Neither the name of the copyright holder 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 HOLDER 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. + +#ifndef SRC_UTILS_CRASH_HANDLER_H_ +#define SRC_UTILS_CRASH_HANDLER_H_ + +namespace dawn { + +// Install crash handler to print a demangled stack trace on unexpected crashes or assertions. +void InstallCrashHandler(const char* argv0); + +} // namespace dawn + +#endif // SRC_UTILS_CRASH_HANDLER_H_
diff --git a/tools/src/cmd/gen/build/BUILD.bazel.tmpl b/tools/src/cmd/gen/build/BUILD.bazel.tmpl index 52130c7..de3a1c2 100644 --- a/tools/src/cmd/gen/build/BUILD.bazel.tmpl +++ b/tools/src/cmd/gen/build/BUILD.bazel.tmpl
@@ -206,6 +206,7 @@ {{- else if eq $.Name "spirv-tools" -}}"@spirv_tools", {{- else if eq $.Name "thread" -}}{{/* unsupported */}} {{- else if eq $.Name "winsock" -}}{{/* unsupported */}} +{{- else if eq $.Name "src_utils_crash_handler" -}}"//src/utils:crash_handler", {{- else if eq $.Name "src_utils" -}}"//src/utils", {{- else if eq $.Name "src_utils_chromium_test_compat" -}}"//src/utils/chromium_test_compat", {{- else -}}{{Error (printf "unhandled external dependency '%v'" $.Name)}}
diff --git a/tools/src/cmd/gen/build/BUILD.gn.tmpl b/tools/src/cmd/gen/build/BUILD.gn.tmpl index c138adc..4a8b3ca 100644 --- a/tools/src/cmd/gen/build/BUILD.gn.tmpl +++ b/tools/src/cmd/gen/build/BUILD.gn.tmpl
@@ -193,6 +193,7 @@ {{- else if eq $.Name "vulkan-headers" -}}"${dawn_vulkan_headers_dir}:vulkan_headers", {{- else if eq $.Name "libvulkan" -}}"${dawn_vulkan_loader_dir}:libvulkan", {{- else if eq $.Name "winsock" -}}"${tint_src_dir}:winsock", +{{- else if eq $.Name "src_utils_crash_handler" -}}"${dawn_root}/src/utils:crash_handler", {{- else if eq $.Name "src_utils" -}}"${dawn_root}/src/utils:utils", {{- else if eq $.Name "src_utils_chromium_test_compat" -}}"${dawn_root}/src/utils/chromium_test_compat:chromium_test_compat", {{- else -}}{{Error (printf "unhandled external dependency '%v'" $.Name)}}