on xenial help sign in
Handle TERM, HUP, and INT signals in unity-scope-tool Fixes: #1470464

Approved by: Albert Astals Cid, Michi Henning

commit0c36be68e3c08988c40babee10c8c029b9f4953a authorMarcus Tomlinson <marcus.tomlinson@canonical.com> dateFri 17 Jul 2015, 15:53 (11 years ago) parent6e300bf01c2a42
4 files changed+202
tools/CMakeLists.txt+1 tools/scopetool.cpp+6 tools/unix-signal-handler.cpp+141 tools/unix-signal-handler.h+54
tools/CMakeLists.txt+1
@@ -1,6 +1,7 @@
11add_executable(${SCOPE_TOOL}
22 scopetool.cpp
33 registry-tracker.cpp
4+ unix-signal-handler.cpp
45 )
56
67qt5_use_modules(${SCOPE_TOOL} Qml Quick)
tools/scopetool.cpp+6
@@ -32,6 +32,7 @@
3232// local
3333#include <paths.h>
3434#include "registry-tracker.h"
35+#include "unix-signal-handler.h"
3536
3637
3738int main(int argc, char *argv[])
@@ -96,6 +97,11 @@ int main(int argc, char *argv[])
9697
9798 view->show();
9899
100+ UnixSignalHandler signal_handler([]{
101+ QGuiApplication::exit(0);
102+ });
103+ signal_handler.setupUnixSignalHandlers();
104+
99105 int result = application->exec();
100106
101107 delete view;
tools/unix-signal-handler.cppnew file+141
@@ -0,0 +1,141 @@
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 "unix-signal-handler.h"
20+
21+#include <QDebug>
22+
23+#include <csignal>
24+#include <sys/socket.h>
25+#include <unistd.h>
26+
27+int UnixSignalHandler::sighupFd[2];
28+int UnixSignalHandler::sigintFd[2];
29+int UnixSignalHandler::sigtermFd[2];
30+
31+UnixSignalHandler::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+
56+void UnixSignalHandler::hupSignalHandler(int)
57+{
58+ char a = 1;
59+ ::write(sighupFd[0], &a, sizeof(a));
60+}
61+
62+void UnixSignalHandler::intSignalHandler(int)
63+{
64+ char a = 1;
65+ ::write(sigintFd[0], &a, sizeof(a));
66+}
67+
68+void UnixSignalHandler::termSignalHandler(int)
69+{
70+ char a = 1;
71+ ::write(sigtermFd[0], &a, sizeof(a));
72+}
73+
74+int 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 = 0;
81+ sighup.sa_flags |= SA_RESTART;
82+
83+ if (sigaction(SIGHUP, &sighup, 0) > 0)
84+ {
85+ return 1;
86+ }
87+
88+ sigint.sa_handler = UnixSignalHandler::intSignalHandler;
89+ sigemptyset(&sigint.sa_mask);
90+ sigint.sa_flags = 0;
91+ sigint.sa_flags |= SA_RESTART;
92+
93+ if (sigaction(SIGINT, &sigint, 0) > 0)
94+ {
95+ return 2;
96+ }
97+
98+ sigterm.sa_handler = UnixSignalHandler::termSignalHandler;
99+ sigemptyset(&sigterm.sa_mask);
100+ sigterm.sa_flags |= SA_RESTART;
101+
102+ if (sigaction(SIGTERM, &sigterm, 0) > 0)
103+ {
104+ return 3;
105+ }
106+
107+ return 0;
108+}
109+
110+void UnixSignalHandler::handleSigHup()
111+{
112+ m_socketNotifierHup->setEnabled(false);
113+ char tmp;
114+ ::read(sighupFd[1], &tmp, sizeof(tmp));
115+
116+ m_func();
117+
118+ m_socketNotifierHup->setEnabled(true);
119+}
120+
121+void UnixSignalHandler::handleSigInt()
122+{
123+ m_socketNotifierInt->setEnabled(false);
124+ char tmp;
125+ ::read(sigintFd[1], &tmp, sizeof(tmp));
126+
127+ m_func();
128+
129+ m_socketNotifierInt->setEnabled(true);
130+}
131+
132+void UnixSignalHandler::handleSigTerm()
133+{
134+ m_socketNotifierTerm->setEnabled(false);
135+ char tmp;
136+ ::read(sigtermFd[1], &tmp, sizeof(tmp));
137+
138+ m_func();
139+
140+ m_socketNotifierTerm->setEnabled(true);
141+}
tools/unix-signal-handler.hnew file+54
@@ -0,0 +1,54 @@
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+#pragma once
20+
21+#include <QObject>
22+#include <QSocketNotifier>
23+
24+#include <functional>
25+
26+class UnixSignalHandler: public QObject {
27+Q_OBJECT
28+
29+public:
30+ UnixSignalHandler(const std::function<void()>& f, QObject *parent = 0);
31+ ~UnixSignalHandler() = default;
32+
33+ static int setupUnixSignalHandlers();
34+
35+protected Q_SLOTS:
36+ void handleSigHup();
37+ void handleSigInt();
38+ void handleSigTerm();
39+
40+protected:
41+ static void hupSignalHandler(int unused);
42+ static void intSignalHandler(int unused);
43+ static void termSignalHandler(int unused);
44+
45+ static int sighupFd[2];
46+ static int sigintFd[2];
47+ static int sigtermFd[2];
48+
49+ std::function<void()> m_func;
50+
51+ QSocketNotifier *m_socketNotifierHup;
52+ QSocketNotifier *m_socketNotifierInt;
53+ QSocketNotifier *m_socketNotifierTerm;
54+};