1 //===--- ThreadCrashReporter.cpp - Thread local signal handling --*- C++-*-===// 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 "llvm/Support/ThreadLocal.h" 11 #include <atomic> 12 13 namespace clang { 14 namespace clangd { 15 16 static thread_local ThreadCrashReporter *CurrentReporter = nullptr; 17 runCrashHandlers()18void ThreadCrashReporter::runCrashHandlers() { 19 // No signal handling is done here on top of what AddSignalHandler() does: 20 // on Windows the signal handling is implmented via 21 // SetUnhandledExceptionFilter() which is thread-directed, and on Unix 22 // platforms the handlers are only called for KillSigs out of which only 23 // SIGQUIT seems to be process-directed and would be delivered to any thread 24 // that is not blocking it, but if the thread it gets delivered to has a 25 // ThreadCrashReporter installed during the interrupt — it seems reasonable to 26 // let it run and print the thread's context information. 27 28 // Call the reporters in LIFO order. 29 ThreadCrashReporter *Reporter = CurrentReporter; 30 while (Reporter) { 31 Reporter->Callback(); 32 Reporter = Reporter->Next; 33 } 34 } 35 ThreadCrashReporter(SignalCallback ThreadLocalCallback)36ThreadCrashReporter::ThreadCrashReporter(SignalCallback ThreadLocalCallback) 37 : Callback(std::move(ThreadLocalCallback)), Next(nullptr) { 38 this->Next = CurrentReporter; 39 CurrentReporter = this; 40 // Don't reorder subsequent operations: whatever comes after might crash and 41 // we want the the crash handler to see the reporter values we just set. 42 std::atomic_signal_fence(std::memory_order_seq_cst); 43 } 44 ~ThreadCrashReporter()45ThreadCrashReporter::~ThreadCrashReporter() { 46 assert(CurrentReporter == this); 47 CurrentReporter = this->Next; 48 // Don't reorder subsequent operations: whatever comes after might crash and 49 // we want the the crash handler to see the reporter values we just set. 50 std::atomic_signal_fence(std::memory_order_seq_cst); 51 } 52 53 } // namespace clangd 54 } // namespace clang 55