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