1 ///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "support/ThreadCrashReporter.h" 10 #include "support/Threading.h" 11 #include "llvm/Support/Signals.h" 12 #include "gtest/gtest.h" 13 #include <csignal> 14 #include <string> 15 16 namespace clang { 17 namespace clangd { 18 19 namespace { 20 infoSignalHandler()21static void infoSignalHandler() { ThreadCrashReporter::runCrashHandlers(); } 22 TEST(ThreadCrashReporterTest,All)23TEST(ThreadCrashReporterTest, All) { 24 #if defined(_WIN32) 25 // Simulate signals on Windows for unit testing purposes. 26 // The `crash.test` lit test checks the end-to-end integration. 27 auto SignalCurrentThread = []() { infoSignalHandler(); }; 28 #else 29 llvm::sys::SetInfoSignalFunction(&infoSignalHandler); 30 auto SignalCurrentThread = []() { raise(SIGUSR1); }; 31 #endif 32 33 AsyncTaskRunner Runner; 34 auto SignalAnotherThread = [&]() { 35 Runner.runAsync("signal another thread", SignalCurrentThread); 36 Runner.wait(); 37 }; 38 39 bool Called; 40 { 41 ThreadCrashReporter ScopedReporter([&Called]() { Called = true; }); 42 // Check handler gets called when a signal gets delivered to the current 43 // thread. 44 Called = false; 45 SignalCurrentThread(); 46 EXPECT_TRUE(Called); 47 48 // Check handler does not get called when another thread gets signalled. 49 Called = false; 50 SignalAnotherThread(); 51 EXPECT_FALSE(Called); 52 } 53 // Check handler does not get called when the reporter object goes out of 54 // scope. 55 Called = false; 56 SignalCurrentThread(); 57 EXPECT_FALSE(Called); 58 59 std::string Order = ""; 60 { 61 ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('a'); }); 62 { 63 ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('b'); }); 64 SignalCurrentThread(); 65 } 66 // Check that handlers are called in LIFO order. 67 EXPECT_EQ(Order, "ba"); 68 69 // Check that current handler is the only one after the nested scope is 70 // over. 71 SignalCurrentThread(); 72 EXPECT_EQ(Order, "baa"); 73 } 74 } 75 76 } // namespace 77 } // namespace clangd 78 } // namespace clang 79