#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>
return;
_W("BEGIN");
+ RestoreSignalAction(SIGUSR2);
+ RestoreSignalAction(SIGUSR1);
#ifndef PRELOAD_ACTIVATE
for (int signo = 0; signo < _NSIG; ++signo)
signal(signo, SIG_DFL);
gc.DoAtFork();
});
+ ChangeSignalAction(SIGUSR1);
+ ChangeSignalAction(SIGUSR2);
+
disposed_ = false;
_W("END");
}
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
#include <unistd.h>
#include <memory>
+#include <unordered_map>
#include <client_socket.hh>
#include <io_channel.hh>
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();
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;
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