#include "fatal_signal.h"
-#include <signal.h>
+#include <csignal>
#include <iostream>
#include <string_view>
FatalSignal::FatalSignal()
{
- auto fatal_signals = {SIGSEGV,
- SIGABRT,
- SIGBUS,
- SIGILL,
- SIGFPE,
- SIGXCPU,
- SIGXFSZ,
- SIGSYS};
-
- for (auto signum : fatal_signals) {
- seastar::engine().handle_signal(signum, [signum, this] {
- signaled(signum);
- });
+ install_oneshot_signals_handler<SIGSEGV,
+ SIGABRT,
+ SIGBUS,
+ SIGILL,
+ SIGFPE,
+ SIGXCPU,
+ SIGXFSZ,
+ SIGSYS>();
+}
+
+template <int... SigNums>
+void FatalSignal::install_oneshot_signals_handler()
+{
+ (install_oneshot_signal_handler<SigNums>() , ...);
+}
+
+template <int SigNum>
+void FatalSignal::install_oneshot_signal_handler()
+{
+ struct sigaction sa;
+ sa.sa_sigaction = [](int sig, siginfo_t *info, void *p) {
+ static std::atomic_bool handled = false;
+ if (handled.exchange(true)) {
+ return;
+ }
+ FatalSignal::signaled(sig);
+ ::signal(sig, SIG_DFL);
+ };
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_RESTART;
+ if constexpr (SigNum == SIGSEGV) {
+ sa.sa_flags |= SA_ONSTACK;
}
+ [[maybe_unused]] auto r = ::sigaction(SigNum, &sa, nullptr);
+ assert(r);
}
+
static void print_with_backtrace(std::string_view cause) {
std::cerr << cause;
if (seastar::engine_is_ready()) {
void FatalSignal::signaled(int signum)
{
- if (handled.exchange(true)) {
- return;
- }
switch (signum) {
case SIGSEGV:
print_with_backtrace("Aborting");
print_with_backtrace(fmt::format("Signal {}", signum));
break;
}
- signal(signum, SIG_DFL);
}
#pragma once
-#include <atomic>
-
class FatalSignal {
public:
FatalSignal();
private:
- void signaled(int signum);
+ static void signaled(int signum);
static void print_backtrace(int signum);
- std::atomic<bool> handled = false;
+
+ template <int... SigNums>
+ void install_oneshot_signals_handler();
+
+ template <int SigNum>
+ void install_oneshot_signal_handler();
};