/* * 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); }