Add SIGUSR1 signal handler 65/300165/3
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 18 Oct 2023 00:03:48 +0000 (09:03 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Wed, 18 Oct 2023 00:21:15 +0000 (09:21 +0900)
Currently, the launchpad-process-pool suddenly gets the SIGUSR1 signal.
To debug the reason, the SIGUSR1 signal handler is added.
While getting the signal, the launchpad-process-pool prints the sender
pid and the backtrace.

Change-Id: I842e374b836b83a635722baafa628bea10f072d0
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/launchpad-process-pool/signal_manager.cc
src/launchpad-process-pool/signal_manager.hh

index 493a75e..51fb638 100644 (file)
 
 #include "launchpad-process-pool/signal_manager.hh"
 
+#include <execinfo.h>
 #include <pthread.h>
+#include <stdio.h>
 #include <sys/signalfd.h>
 
 #include <filesystem>
+#include <fstream>
 #include <memory>
 #include <string>
 #include <vector>
@@ -126,6 +129,8 @@ void SignalManager::Dispose() {
     return;
 
   _W("BEGIN");
+  RestoreSignalAction(SIGUSR2);
+  RestoreSignalAction(SIGUSR1);
 #ifndef PRELOAD_ACTIVATE
   for (int signo = 0; signo < _NSIG; ++signo)
     signal(signo, SIG_DFL);
@@ -174,6 +179,9 @@ void SignalManager::Init() {
         gc.DoAtFork();
       });
 
+  ChangeSignalAction(SIGUSR1);
+  ChangeSignalAction(SIGUSR2);
+
   disposed_ = false;
   _W("END");
 }
@@ -231,4 +239,66 @@ void SignalManager::OnHydraSigchld(pid_t pid, int status) {
   HandleSigchld(pid, status);
 }
 
+void SignalManager::ChangeSignalAction(int signo) {
+  struct sigaction old_action = { 0, };
+  struct sigaction action = { 0, };
+  sigemptyset(&action.sa_mask);
+  action.sa_sigaction = UnixSignalHandler;
+  action.sa_flags = SA_RESTART | SA_SIGINFO;
+
+  int ret = sigaction(signo, &action, &old_action);
+  if (ret != 0) {
+    _W("sigaction() is failed. errno(%d)", errno);
+    return;
+  }
+
+  sigaction_map_[signo] = std::make_unique<SignalAction>(signo, old_action);
+}
+
+void SignalManager::RestoreSignalAction(int signo) {
+  auto found = sigaction_map_.find(signo);
+  if (found == sigaction_map_.end()) {
+    _W("Failed to find signal action. signo(%d)", signo);
+    return;
+  }
+
+  auto& signal_action = found->second;
+  auto old_action = signal_action->GetSigaction();
+  sigaction(signo, &old_action, nullptr);
+  sigaction_map_.erase(found);
+}
+
+void SignalManager::UnixSignalHandler(int signo, siginfo_t* info, void* arg) {
+#define BT_BUF_SIZE 128
+  sigset_t old_mask;
+  sigset_t mask;
+  sigfillset(&mask);
+  sigprocmask(SIG_BLOCK, &mask, &old_mask);
+
+  _W("[UNIX_SIGNAL_HANDLER] signo: %d", signo);
+  if (info != nullptr) {
+    _W("[UNIX_SIGNAL_HANDLER] pid: %d, uid: %u", info->si_pid, info->si_uid);
+    if (info->si_pid > 0) {
+      std::ifstream stream("/proc/" + std::to_string(info->si_pid) +
+          "/cmdline");
+      if (stream.is_open()) {
+        std::string cmdline;
+        std::getline(stream, cmdline);
+        stream.close();
+        _W("[UNIX_SIGNAL_HANDLER] cmdline: %s", cmdline.c_str());
+      }
+    }
+  }
+
+  void* buffer[BT_BUF_SIZE];
+  int nptrs = backtrace(buffer, BT_BUF_SIZE);
+  backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
+
+  sigprocmask(SIG_SETMASK, &old_mask, nullptr);
+  raise(signo);
+
+  _W("Raise SIGABRT to make coredump");
+  abort();
+}
+
 }  // namespace launchpad
index 8cd8ffc..66acf22 100644 (file)
@@ -22,6 +22,7 @@
 #include <unistd.h>
 
 #include <memory>
+#include <unordered_map>
 
 #include <client_socket.hh>
 #include <io_channel.hh>
@@ -54,6 +55,19 @@ class SignalManager : public SigchldEvent::IEvent,
   void UnblockSigchld();
 
  private:
+  class SignalAction {
+   public:
+    SignalAction(int signo, struct sigaction action)
+        : signo_(signo), action_(action) {}
+
+    int GetSigno() const { return signo_; };
+    struct sigaction GetSigaction() const { return action_; };
+
+   private:
+    int signo_;
+    struct sigaction action_;
+  };
+
   SignalManager() = default;
   ~SignalManager();
 
@@ -65,6 +79,10 @@ class SignalManager : public SigchldEvent::IEvent,
   void OnSigchld(pid_t pid, int status) override;
   void OnHydraSigchld(pid_t pid, int status) override;
 
+  void ChangeSignalAction(int signo);
+  void RestoreSignalAction(int signo);
+  static void UnixSignalHandler(int signo, siginfo_t* info, void* arg);
+
  private:
   bool disposed_ = true;
   IEvent* listener_ = nullptr;
@@ -73,6 +91,7 @@ class SignalManager : public SigchldEvent::IEvent,
   std::unique_ptr<SigchldEvent> sigchld_event_;
   std::unique_ptr<HydraSigchldEvent> hydra_sigchld_event_;
   std::unique_ptr<Worker> recycle_bin_;
+  std::unordered_map<int, std::unique_ptr<SignalAction>> sigaction_map_;
 };
 
 }  // namespace launchpad