1*045695f8SEmma Blink //===--- ThreadCrashReporter.h - Thread local signal handling ----*- C++-*-===// 2*045695f8SEmma Blink // 3*045695f8SEmma Blink // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*045695f8SEmma Blink // See https://llvm.org/LICENSE.txt for license information. 5*045695f8SEmma Blink // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*045695f8SEmma Blink // 7*045695f8SEmma Blink //===----------------------------------------------------------------------===// 8*045695f8SEmma Blink 9*045695f8SEmma Blink #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADCRASHREPORTER_H 10*045695f8SEmma Blink #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADCRASHREPORTER_H 11*045695f8SEmma Blink 12*045695f8SEmma Blink #include "llvm/ADT/FunctionExtras.h" 13*045695f8SEmma Blink 14*045695f8SEmma Blink namespace clang { 15*045695f8SEmma Blink namespace clangd { 16*045695f8SEmma Blink 17*045695f8SEmma Blink /// Allows setting per-thread abort/kill signal callbacks, to print additional 18*045695f8SEmma Blink /// information about the crash depending on which thread got signalled. 19*045695f8SEmma Blink class ThreadCrashReporter { 20*045695f8SEmma Blink public: 21*045695f8SEmma Blink using SignalCallback = llvm::unique_function<void(void)>; 22*045695f8SEmma Blink 23*045695f8SEmma Blink /// Registers the callback as the first one in thread-local callback chain. 24*045695f8SEmma Blink /// 25*045695f8SEmma Blink /// Asserts if the current thread's callback is already set. The callback is 26*045695f8SEmma Blink /// likely to be invoked in a signal handler. Most LLVM signal handling is not 27*045695f8SEmma Blink /// strictly async-signal-safe. However reporters should avoid accessing data 28*045695f8SEmma Blink /// structures likely to be in a bad state on crash. 29*045695f8SEmma Blink ThreadCrashReporter(SignalCallback ThreadLocalCallback); 30*045695f8SEmma Blink /// Resets the current thread's callback to nullptr. 31*045695f8SEmma Blink ~ThreadCrashReporter(); 32*045695f8SEmma Blink 33*045695f8SEmma Blink /// Moves are disabled to ease nesting and escaping considerations. 34*045695f8SEmma Blink ThreadCrashReporter(ThreadCrashReporter &&RHS) = delete; 35*045695f8SEmma Blink ThreadCrashReporter(const ThreadCrashReporter &) = delete; 36*045695f8SEmma Blink ThreadCrashReporter &operator=(ThreadCrashReporter &&) = delete; 37*045695f8SEmma Blink ThreadCrashReporter &operator=(const ThreadCrashReporter &) = delete; 38*045695f8SEmma Blink 39*045695f8SEmma Blink /// Calls all currently-active ThreadCrashReporters for the current thread. 40*045695f8SEmma Blink /// 41*045695f8SEmma Blink /// To be called from sys::AddSignalHandler() callback. Any signal filtering 42*045695f8SEmma Blink /// is the responsibility of the caller. While this function is intended to be 43*045695f8SEmma Blink /// called from signal handlers, it is not strictly async-signal-safe - see 44*045695f8SEmma Blink /// constructor comment. 45*045695f8SEmma Blink /// 46*045695f8SEmma Blink /// When several reporters are nested, the callbacks are called in LIFO order. 47*045695f8SEmma Blink static void runCrashHandlers(); 48*045695f8SEmma Blink 49*045695f8SEmma Blink private: 50*045695f8SEmma Blink SignalCallback Callback; 51*045695f8SEmma Blink /// Points to the next reporter up the stack. 52*045695f8SEmma Blink ThreadCrashReporter *Next; 53*045695f8SEmma Blink }; 54*045695f8SEmma Blink 55*045695f8SEmma Blink } // namespace clangd 56*045695f8SEmma Blink } // namespace clang 57*045695f8SEmma Blink 58*045695f8SEmma Blink #endif 59