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