]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/common: don't use Seastar's handle_signal() for fatal signals.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 19 Apr 2021 14:32:05 +0000 (14:32 +0000)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 19 Apr 2021 15:24:04 +0000 (15:24 +0000)
The `handle_signal()` way requires going through the reactor, and
thus is unsuitable for situations when it's no longer operational.
SIGSEGV generated as a result of actual fault (not `kill()`) is
the intended audience of this change.

Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/common/fatal_signal.cc
src/crimson/common/fatal_signal.h

index 55988d903fe3603a19933a52913f723ef14b962f..a03259a86820e7fe72d9be2a1f95088c7a175671 100644 (file)
@@ -3,7 +3,7 @@
 
 #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()) {
@@ -43,9 +65,6 @@ static void print_with_backtrace(std::string_view cause) {
 
 void FatalSignal::signaled(int signum)
 {
-  if (handled.exchange(true)) {
-    return;
-  }
   switch (signum) {
   case SIGSEGV:
     print_with_backtrace("Aborting");
@@ -57,5 +76,4 @@ void FatalSignal::signaled(int signum)
     print_with_backtrace(fmt::format("Signal {}", signum));
     break;
   }
-  signal(signum, SIG_DFL);
 }
index 8320f99d690508a390cbe6b3c61cfadc88d62734..158b87f0c76825009350611d3dce926fccc86fcb 100644 (file)
@@ -3,14 +3,17 @@
 
 #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();
 };