xref: /llvm-project/clang-tools-extra/clangd/support/ThreadCrashReporter.h (revision 045695f85cb8cdf9b8373123749efe1781f337b4)
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