/*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Marcus Tomlinson
*/
#include "UnixSignalHandler.h"
#include
#include
#include
#include
int UnixSignalHandler::sighupFd[2];
int UnixSignalHandler::sigintFd[2];
int UnixSignalHandler::sigtermFd[2];
UnixSignalHandler::UnixSignalHandler(const std::function& f, QObject *parent)
: QObject(parent),
m_func(f)
{
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighupFd))
{
qFatal("Couldn't create HUP socketpair");
}
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFd))
{
qFatal("Couldn't create INT socketpair");
}
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd))
{
qFatal("Couldn't create TERM socketpair");
}
m_socketNotifierHup = new QSocketNotifier(sighupFd[1], QSocketNotifier::Read, this);
connect(m_socketNotifierHup, &QSocketNotifier::activated, this, &UnixSignalHandler::handleSigHup);
m_socketNotifierInt = new QSocketNotifier(sigintFd[1], QSocketNotifier::Read, this);
connect(m_socketNotifierInt, &QSocketNotifier::activated, this, &UnixSignalHandler::handleSigInt);
m_socketNotifierTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this);
connect(m_socketNotifierTerm, &QSocketNotifier::activated, this, &UnixSignalHandler::handleSigTerm);
}
void UnixSignalHandler::hupSignalHandler(int)
{
char a = 1;
::write(sighupFd[0], &a, sizeof(a));
}
void UnixSignalHandler::intSignalHandler(int)
{
char a = 1;
::write(sigintFd[0], &a, sizeof(a));
}
void UnixSignalHandler::termSignalHandler(int)
{
char a = 1;
::write(sigtermFd[0], &a, sizeof(a));
}
int UnixSignalHandler::setupUnixSignalHandlers()
{
struct sigaction sighup, sigint, sigterm;
sighup.sa_handler = UnixSignalHandler::hupSignalHandler;
sigemptyset(&sighup.sa_mask);
sighup.sa_flags = SA_RESTART;
if (sigaction(SIGHUP, &sighup, 0) > 0)
{
return 1;
}
sigint.sa_handler = UnixSignalHandler::intSignalHandler;
sigemptyset(&sigint.sa_mask);
sigint.sa_flags = SA_RESTART;
if (sigaction(SIGINT, &sigint, 0) > 0)
{
return 2;
}
sigterm.sa_handler = UnixSignalHandler::termSignalHandler;
sigemptyset(&sigterm.sa_mask);
sigterm.sa_flags = SA_RESTART;
if (sigaction(SIGTERM, &sigterm, 0) > 0)
{
return 3;
}
return 0;
}
void UnixSignalHandler::handleSigHup()
{
m_socketNotifierHup->setEnabled(false);
char tmp;
::read(sighupFd[1], &tmp, sizeof(tmp));
m_func();
m_socketNotifierHup->setEnabled(true);
}
void UnixSignalHandler::handleSigInt()
{
m_socketNotifierInt->setEnabled(false);
char tmp;
::read(sigintFd[1], &tmp, sizeof(tmp));
m_func();
m_socketNotifierInt->setEnabled(true);
}
void UnixSignalHandler::handleSigTerm()
{
m_socketNotifierTerm->setEnabled(false);
char tmp;
::read(sigtermFd[1], &tmp, sizeof(tmp));
m_func();
m_socketNotifierTerm->setEnabled(true);
}