2#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3#include <QtSystemDetection>
6#include <QSocketNotifier>
7#include <QCoreApplication>
19#include <sys/socket.h>
33static const std::array<
const int, 6
36#if !defined(Q_OS_DARWIN) && !defined(Q_OS_OPENBSD)
42 SIGINT, SIGTERM, SIGSEGV, SIGABRT, SIGFPE, SIGILL,
45#if !defined(Q_OS_DARWIN) && !defined(Q_OS_OPENBSD)
54std::array<std::string,SIG_STR_COUNT>
sig_str;
61 sig_str[sig] = qPrintable(QString(
"Handling %1\n").arg(name));
66 for (
size_t i = 0; i <
sig_str.size(); i++)
67 sig_str_init(i, qPrintable(QString(
"Signal %1").arg(i)));
82 stack.ss_size = SIGSTKSZ;
85 if (sigaltstack(&stack,
nullptr) == -1)
87 std::cerr <<
"Couldn't create signal stack!" << std::endl;
92 if (::socketpair(AF_UNIX, SOCK_STREAM, 0,
s_sigFd.data()))
94 std::cerr <<
"Couldn't create socketpair" << std::endl;
124 int signum = it.key();
125 signal(signum, SIG_DFL);
160 const char *signame = strsignal(signum);
161 QString signal_name = signame ?
162 QString(signame) : QString(
"Unknown(%1)").arg(signum);
164 bool sa_handler_already_set =
false;
167 sa_handler_already_set =
m_sigMap.contains(signum);
168 if (
m_sigMap.value(signum,
nullptr) && (handler !=
nullptr))
170 LOG(VB_GENERAL, LOG_WARNING,
171 QString(
"Warning %1 signal handler overridden")
177 if (!sa_handler_already_set)
179 struct sigaction sa {};
181 sigemptyset(&sa.sa_mask);
182 sa.sa_flags = SA_RESTART | SA_SIGINFO;
184 sa.sa_flags |= SA_ONSTACK;
188 sigaction(signum, &sa,
nullptr);
191 LOG(VB_GENERAL, LOG_INFO, QString(
"Setup %1 handler").arg(signal_name));
205 [[maybe_unused]]
void *context)
211 signalInfo.m_code = 0;
212 signalInfo.m_pid = 0;
213 signalInfo.m_uid = 0;
214 signalInfo.m_value = 0;
216 signalInfo.m_code = (
info ?
info->si_code : 0);
217 signalInfo.m_pid = (
info ? (int)
info->si_pid : 0);
218 signalInfo.m_uid = (
info ? (int)
info->si_uid : 0);
219 signalInfo.m_value = (
info ?
info->si_value.sival_int : 0);
225 char *buffer = (
char *)&signalInfo;
256 signal(signum, SIG_DFL);
271 if (signum <
static_cast<int>(
sig_str.size()))
282 signal(signum, SIG_DFL);
294 bool infoComplete = (ret ==
sizeof(
SignalInfo));
295 int signum = (infoComplete ? signalInfo.m_signum : 0);
299 QString signame = strsignal(signum);
300 if (signame.isEmpty())
301 signame =
"Unknown Signal";
302 LOG(VB_GENERAL, LOG_CRIT,
303 QString(
"Received %1: Code %2, PID %3, UID %4, Value 0x%5")
304 .arg(signame) .arg(signalInfo.m_code) .arg(signalInfo.m_pid)
305 .arg(signalInfo.m_uid) .arg(signalInfo.m_value,8,16,QChar(
'0')));
309 bool allowNullHandler =
false;
311#if !defined(Q_OS_DARWIN) && !defined(Q_OS_OPENBSD)
312 if (signum == SIGRTMIN)
317 allowNullHandler =
true;
326 handler =
m_sigMap.value(signum,
nullptr);
332 QCoreApplication::exit(0);
340 std::this_thread::sleep_for(100ms);
345 handler =
m_sigMap.value(signum,
nullptr);
351 else if (!allowNullHandler)
353 LOG(VB_GENERAL, LOG_CRIT, QString(
"Received unexpected signal %1")
A container object to handle UNIX signals in the Qt space correctly.
static QMutex s_singletonLock
static std::array< int, 2 > s_sigFd
static SignalHandler * s_singleton
void SetHandlerPrivate(int signum, SigHandlerFunc handler)
QSocketNotifier * m_notifier
~SignalHandler() override
static void SetHandler(int signum, SigHandlerFunc handler)
static void signalHandler(int signum, siginfo_t *info, void *context)
QMap< int, SigHandlerFunc > m_sigMap
SignalHandler(QObject *parent)
static volatile bool s_exit_program
static void Init(QObject *parent=nullptr)
static const iso6937table * d
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
def read(device=None, features=[])
def write(text, progress=True)
static constexpr size_t SIG_STR_COUNT
static const std::array< const int, 6 > kDefaultSignalList
static void sig_str_init(size_t sig, const char *name)
std::array< std::string, SIG_STR_COUNT > sig_str
void(*)(void) SigHandlerFunc