AusweisApp2/src/core/SignalHandler_bsd_linux_osx...

83 lines
1.9 KiB
C++

/*
* \copyright Copyright (c) 2016-2019 Governikus GmbH & Co. KG, Germany
*/
#include "SignalHandler.h"
#include "SingletonHelper.h"
#include <QCoreApplication>
#include <QLoggingCategory>
#include <sys/socket.h>
#include <unistd.h>
using namespace governikus;
Q_DECLARE_LOGGING_CATEGORY(system)
int SignalHandler::cSignalSocketPair[2];
void SignalHandler::initUnix()
{
// Signal handling on POSIX systems is some what messed up since there exists
// only a limited set of API calls which are usable. Therefore we create a private
// socketpair to cross thread borders.
// http://doc.qt.io/qt-5/unix-signals.html
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, cSignalSocketPair))
{
qCCritical(system) << "** Failed to set up socket pair for signaling! **";
return;
}
mSignalSocketNotifier.reset(new QSocketNotifier(cSignalSocketPair[1], QSocketNotifier::Read));
mSignalSocketNotifier->setEnabled(true);
connect(mSignalSocketNotifier.data(), &QSocketNotifier::activated, this, &SignalHandler::onSignalSocketActivated);
::signal(SIGINT, sigHandler);
::signal(SIGTERM, sigHandler);
::signal(SIGHUP, sigHandler);
::signal(SIGQUIT, sigHandler);
}
void SignalHandler::sigHandler(int pSignal)
{
if (::write(cSignalSocketPair[0], &pSignal, sizeof(pSignal)) != sizeof(pSignal))
{
qCWarning(system) << "Cannot bind signal:" << pSignal;
}
}
void SignalHandler::onSignalSocketActivated()
{
mSignalSocketNotifier->setEnabled(false);
int signal = -1;
const auto bytes = ::read(cSignalSocketPair[1], &signal, sizeof(signal));
if (bytes == 0 || signal == -1)
{
qCWarning(system) << "Cannot read signal:" << signal << "| bytes:" << bytes;
return;
}
qCWarning(system) << "Got signal:" << signal;
switch (signal)
{
case SIGINT:
case SIGTERM:
case SIGHUP:
case SIGQUIT:
getInstance().quit();
break;
default:
break;
}
mSignalSocketNotifier->setEnabled(true);
}