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