Lomiri
Loading...
Searching...
No Matches
UnixSignalHandler.cpp
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Marcus Tomlinson <marcus.tomlinson@canonical.com>
17 */
18
19#include "UnixSignalHandler.h"
20
21#include <QDebug>
22
23#include <csignal>
24#include <sys/socket.h>
25#include <unistd.h>
26
27int UnixSignalHandler::sighupFd[2];
28int UnixSignalHandler::sigintFd[2];
29int UnixSignalHandler::sigtermFd[2];
30
31UnixSignalHandler::UnixSignalHandler(const std::function<void()>& f, QObject *parent)
32 : QObject(parent),
33 m_func(f)
34{
35 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighupFd))
36 {
37 qFatal("Couldn't create HUP socketpair");
38 }
39 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFd))
40 {
41 qFatal("Couldn't create INT socketpair");
42 }
43 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd))
44 {
45 qFatal("Couldn't create TERM socketpair");
46 }
47
48 m_socketNotifierHup = new QSocketNotifier(sighupFd[1], QSocketNotifier::Read, this);
49 connect(m_socketNotifierHup, &QSocketNotifier::activated, this, &UnixSignalHandler::handleSigHup);
50 m_socketNotifierInt = new QSocketNotifier(sigintFd[1], QSocketNotifier::Read, this);
51 connect(m_socketNotifierInt, &QSocketNotifier::activated, this, &UnixSignalHandler::handleSigInt);
52 m_socketNotifierTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this);
53 connect(m_socketNotifierTerm, &QSocketNotifier::activated, this, &UnixSignalHandler::handleSigTerm);
54}
55
56void UnixSignalHandler::hupSignalHandler(int)
57{
58 char a = 1;
59 ::write(sighupFd[0], &a, sizeof(a));
60}
61
62void UnixSignalHandler::intSignalHandler(int)
63{
64 char a = 1;
65 ::write(sigintFd[0], &a, sizeof(a));
66}
67
68void UnixSignalHandler::termSignalHandler(int)
69{
70 char a = 1;
71 ::write(sigtermFd[0], &a, sizeof(a));
72}
73
74int UnixSignalHandler::setupUnixSignalHandlers()
75{
76 struct sigaction sighup, sigint, sigterm;
77
78 sighup.sa_handler = UnixSignalHandler::hupSignalHandler;
79 sigemptyset(&sighup.sa_mask);
80 sighup.sa_flags = SA_RESTART;
81
82 if (sigaction(SIGHUP, &sighup, 0) > 0)
83 {
84 return 1;
85 }
86
87 sigint.sa_handler = UnixSignalHandler::intSignalHandler;
88 sigemptyset(&sigint.sa_mask);
89 sigint.sa_flags = SA_RESTART;
90
91 if (sigaction(SIGINT, &sigint, 0) > 0)
92 {
93 return 2;
94 }
95
96 sigterm.sa_handler = UnixSignalHandler::termSignalHandler;
97 sigemptyset(&sigterm.sa_mask);
98 sigterm.sa_flags = SA_RESTART;
99
100 if (sigaction(SIGTERM, &sigterm, 0) > 0)
101 {
102 return 3;
103 }
104
105 return 0;
106}
107
108void UnixSignalHandler::handleSigHup()
109{
110 m_socketNotifierHup->setEnabled(false);
111 char tmp;
112 ::read(sighupFd[1], &tmp, sizeof(tmp));
113
114 m_func();
115
116 m_socketNotifierHup->setEnabled(true);
117}
118
119void UnixSignalHandler::handleSigInt()
120{
121 m_socketNotifierInt->setEnabled(false);
122 char tmp;
123 ::read(sigintFd[1], &tmp, sizeof(tmp));
124
125 m_func();
126
127 m_socketNotifierInt->setEnabled(true);
128}
129
130void UnixSignalHandler::handleSigTerm()
131{
132 m_socketNotifierTerm->setEnabled(false);
133 char tmp;
134 ::read(sigtermFd[1], &tmp, sizeof(tmp));
135
136 m_func();
137
138 m_socketNotifierTerm->setEnabled(true);
139}