forked from OSchip/llvm-project
56 lines
2.1 KiB
C++
56 lines
2.1 KiB
C++
//===--- ThreadCrashReporter.cpp - Thread local signal handling --*- C++-*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "support/ThreadCrashReporter.h"
|
|
#include "llvm/Support/Signals.h"
|
|
#include "llvm/Support/ThreadLocal.h"
|
|
#include <atomic>
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
|
|
static thread_local ThreadCrashReporter *CurrentReporter = nullptr;
|
|
|
|
void ThreadCrashReporter::runCrashHandlers() {
|
|
// No signal handling is done here on top of what AddSignalHandler() does:
|
|
// on Windows the signal handling is implmented via
|
|
// SetUnhandledExceptionFilter() which is thread-directed, and on Unix
|
|
// platforms the handlers are only called for KillSigs out of which only
|
|
// SIGQUIT seems to be process-directed and would be delivered to any thread
|
|
// that is not blocking it, but if the thread it gets delivered to has a
|
|
// ThreadCrashReporter installed during the interrupt — it seems reasonable to
|
|
// let it run and print the thread's context information.
|
|
|
|
// Call the reporters in LIFO order.
|
|
ThreadCrashReporter *Reporter = CurrentReporter;
|
|
while (Reporter) {
|
|
Reporter->Callback();
|
|
Reporter = Reporter->Next;
|
|
}
|
|
}
|
|
|
|
ThreadCrashReporter::ThreadCrashReporter(SignalCallback ThreadLocalCallback)
|
|
: Callback(std::move(ThreadLocalCallback)), Next(nullptr) {
|
|
this->Next = CurrentReporter;
|
|
CurrentReporter = this;
|
|
// Don't reorder subsequent operations: whatever comes after might crash and
|
|
// we want the the crash handler to see the reporter values we just set.
|
|
std::atomic_signal_fence(std::memory_order_seq_cst);
|
|
}
|
|
|
|
ThreadCrashReporter::~ThreadCrashReporter() {
|
|
assert(CurrentReporter == this);
|
|
CurrentReporter = this->Next;
|
|
// Don't reorder subsequent operations: whatever comes after might crash and
|
|
// we want the the crash handler to see the reporter values we just set.
|
|
std::atomic_signal_fence(std::memory_order_seq_cst);
|
|
}
|
|
|
|
} // namespace clangd
|
|
} // namespace clang
|