Merge lp:~zsombi/ubuntu-ui-toolkit/statesaver-signals into lp:ubuntu-ui-toolkit

Proposed by Zsombor Egri
Status: Merged
Approved by: Tim Peeters
Approved revision: 969
Merged at revision: 985
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/statesaver-signals
Merge into: lp:ubuntu-ui-toolkit
Prerequisite: lp:~zsombi/ubuntu-ui-toolkit/statesaver-discard-shutdown
Diff against target: 330 lines (+242/-2)
7 files modified
modules/Ubuntu/Components/plugin/plugin.pro (+4/-2)
modules/Ubuntu/Components/plugin/statesaverbackend_p.cpp (+18/-0)
modules/Ubuntu/Components/plugin/statesaverbackend_p.h (+1/-0)
modules/Ubuntu/Components/plugin/unixsignalhandler_p.cpp (+84/-0)
modules/Ubuntu/Components/plugin/unixsignalhandler_p.h (+60/-0)
tests/unit_x11/tst_statesaver/SimpleApp.qml (+28/-0)
tests/unit_x11/tst_statesaver/tst_statesaver.cpp (+47/-0)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/statesaver-signals
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Florian Boucault (community) Needs Fixing
Review via email: mp+205184@code.launchpad.net

Commit message

StateSaver does cleanup if the app is closed due to SIGTERM. This is needed as upstart sends this signal when the application is closed from app scope. SIGINT saves the state.

To post a comment you must log in.
942. By Zsombor Egri

prereq merge

943. By Zsombor Egri

prereq merge

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Florian Boucault (fboucault) wrote :

1) modules/Ubuntu/Components/plugin/statesaverbackend_p.h has a dead/commented include
2) modules/Ubuntu/Components/plugin/statesaverbackend_p.cpp has a qDebug() leftover

review: Needs Fixing
944. By Zsombor Egri

prerequisite merge

945. By Zsombor Egri

commented code removed

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 1) modules/Ubuntu/Components/plugin/statesaverbackend_p.h has a dead/commented
> include
> 2) modules/Ubuntu/Components/plugin/statesaverbackend_p.cpp has a qDebug()
> leftover

Done.

946. By Zsombor Egri

make read/write values unused to satisfy compilation

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
947. By Zsombor Egri

suppress read and write return value warning

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
948. By Zsombor Egri

prereq merge

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
949. By Zsombor Egri

prereq sync

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
950. By Zsombor Egri

kick2

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
951. By Zsombor Egri

prereq merge

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
952. By Zsombor Egri

more logs in runtest.sh

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
953. By Zsombor Egri

more logs

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
954. By Zsombor Egri

missing include

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
955. By Zsombor Egri

remove SIGINT handling

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
956. By Zsombor Egri

remove SIGTERM, SIGINT on

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
957. By Zsombor Egri

signal hooks disabled

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
958. By Zsombor Egri

disabling signal tests

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
959. By Zsombor Egri

re-enable SIGTERM test

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
960. By Zsombor Egri

revert changes

961. By Zsombor Egri

SIGINT test removed

962. By Zsombor Egri

prereq merge

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
963. By Zsombor Egri

put the SIGINT test back

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
964. By Zsombor Egri

use kill() to send SIGINT

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
965. By Zsombor Egri

prereq merge

966. By Zsombor Egri

fail if the PID to be killed is the same as the application's PID

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
967. By Zsombor Egri

different way to check pid

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
968. By Zsombor Egri

skip test if app PID is 0

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
969. By Zsombor Egri

skip test if child pid is 0

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

tested with latest proposed image

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'modules/Ubuntu/Components/plugin/plugin.pro'
2--- modules/Ubuntu/Components/plugin/plugin.pro 2014-03-05 12:29:58 +0000
3+++ modules/Ubuntu/Components/plugin/plugin.pro 2014-03-26 19:26:16 +0000
4@@ -59,7 +59,8 @@
5 ucstatesaver_p.h \
6 ucurihandler.h \
7 ucinversemouse.h \
8- ucmouse.h
9+ ucmouse.h \
10+ unixsignalhandler_p.h
11
12 SOURCES += plugin.cpp \
13 uctheme.cpp \
14@@ -88,7 +89,8 @@
15 ucstatesaver.cpp \
16 statesaverbackend_p.cpp \
17 ucurihandler.cpp \
18- ucmousefilters.cpp
19+ ucmousefilters.cpp \
20+ unixsignalhandler_p.cpp
21
22 # adapters
23 SOURCES += adapters/alarmsadapter_organizer.cpp
24
25=== modified file 'modules/Ubuntu/Components/plugin/statesaverbackend_p.cpp'
26--- modules/Ubuntu/Components/plugin/statesaverbackend_p.cpp 2014-03-26 19:26:15 +0000
27+++ modules/Ubuntu/Components/plugin/statesaverbackend_p.cpp 2014-03-26 19:26:16 +0000
28@@ -29,6 +29,8 @@
29 #include "quickutils.h"
30 #include <QtCore/QStandardPaths>
31
32+#include "unixsignalhandler_p.h"
33+
34 StateSaverBackend::StateSaverBackend(QObject *parent)
35 : QObject(parent)
36 , m_archive(0)
37@@ -47,6 +49,11 @@
38 QObject::connect(&UCApplication::instance(), &UCApplication::applicationNameChanged,
39 this, &StateSaverBackend::initialize);
40 }
41+
42+ UnixSignalHandler::instance().connectSignal(UnixSignalHandler::Terminate);
43+ UnixSignalHandler::instance().connectSignal(UnixSignalHandler::Interrupt);
44+ QObject::connect(&UnixSignalHandler::instance(), SIGNAL(signalTriggered(int)),
45+ this, SLOT(signalHandler(int)));
46 }
47
48 StateSaverBackend::~StateSaverBackend()
49@@ -74,6 +81,17 @@
50 m_archive.clear();
51 }
52
53+void StateSaverBackend::signalHandler(int type)
54+{
55+ if (type == UnixSignalHandler::Interrupt) {
56+ Q_EMIT initiateStateSaving();
57+ // disconnect aboutToQuit() so the state file doesn't get wiped upon quit
58+ QObject::disconnect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
59+ this, &StateSaverBackend::cleanup);
60+ }
61+ QCoreApplication::quit();
62+}
63+
64 bool StateSaverBackend::enabled() const
65 {
66 return m_globalEnabled;
67
68=== modified file 'modules/Ubuntu/Components/plugin/statesaverbackend_p.h'
69--- modules/Ubuntu/Components/plugin/statesaverbackend_p.h 2014-02-06 20:50:13 +0000
70+++ modules/Ubuntu/Components/plugin/statesaverbackend_p.h 2014-03-26 19:26:16 +0000
71@@ -59,6 +59,7 @@
72 private Q_SLOTS:
73 void initialize();
74 void cleanup();
75+ void signalHandler(int type);
76
77 private:
78 QPointer<QSettings> m_archive;
79
80=== added file 'modules/Ubuntu/Components/plugin/unixsignalhandler_p.cpp'
81--- modules/Ubuntu/Components/plugin/unixsignalhandler_p.cpp 1970-01-01 00:00:00 +0000
82+++ modules/Ubuntu/Components/plugin/unixsignalhandler_p.cpp 2014-03-26 19:26:16 +0000
83@@ -0,0 +1,84 @@
84+/*
85+ * Copyright 2014 Canonical Ltd.
86+ *
87+ * This program is free software; you can redistribute it and/or modify
88+ * it under the terms of the GNU Lesser General Public License as published by
89+ * the Free Software Foundation; version 3.
90+ *
91+ * This program is distributed in the hope that it will be useful,
92+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
93+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94+ * GNU Lesser General Public License for more details.
95+ *
96+ * You should have received a copy of the GNU Lesser General Public License
97+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
98+ *
99+ */
100+
101+#include "unixsignalhandler_p.h"
102+#include <sys/socket.h>
103+#include <signal.h>
104+#include <unistd.h>
105+#include <QtCore/QSocketNotifier>
106+
107+UnixSignalHandler::UnixSignalHandler(QObject *parent) :
108+ QObject(parent)
109+{
110+}
111+
112+void UnixSignalHandler::connectSignal(SignalType type)
113+{
114+ if (notifiers.contains(type)) {
115+ return;
116+ }
117+
118+ HandlerType handler = createHandler((int)type);
119+ notifiers.insert(type, handler);
120+ socketRegister.insert(handler.first[1], type);
121+}
122+
123+UnixSignalHandler::HandlerType UnixSignalHandler::createHandler(int signal)
124+{
125+ struct sigaction sigAction;
126+ sigAction.sa_handler = signalHook;
127+ ::sigemptyset(&sigAction.sa_mask);
128+ sigAction.sa_flags = SA_RESTART;
129+
130+ if (::sigaction(signal, &sigAction, 0) > 0) {
131+ qFatal("UNIX signal registration error");
132+ }
133+ HandlerType handler;
134+ if (::socketpair(AF_UNIX, SOCK_STREAM, 0, handler.first)) {
135+ qFatal("Cannot create signal socketpair");
136+ }
137+ handler.second = new QSocketNotifier(handler.first[1], QSocketNotifier::Read, this);
138+ QObject::connect(handler.second, SIGNAL(activated(int)), this, SLOT(notifierActivated(int)));
139+
140+ return handler;
141+}
142+
143+void UnixSignalHandler::signalHook(int signal)
144+{
145+ HandlerType handler = UnixSignalHandler::instance().notifiers.value((SignalType)signal);
146+ char value = 1;
147+ ssize_t size = ::write(handler.first[0], &value, sizeof(value));
148+ // this is needed to suppress write return value warning
149+ Q_UNUSED(size)
150+}
151+
152+void UnixSignalHandler::notifierActivated(int socket)
153+{
154+ // get the socket from the hash
155+ SignalType signal = socketRegister.value(socket);
156+ HandlerType handler = notifiers.value(signal);
157+
158+ handler.second->setEnabled(false);
159+ char value;
160+ ssize_t size = ::read(handler.first[1], &value, sizeof(value));
161+ // this is needed to suppress read return value warning
162+ Q_UNUSED(size)
163+
164+ Q_EMIT signalTriggered(signal);
165+
166+ handler.second->setEnabled(true);
167+}
168
169=== added file 'modules/Ubuntu/Components/plugin/unixsignalhandler_p.h'
170--- modules/Ubuntu/Components/plugin/unixsignalhandler_p.h 1970-01-01 00:00:00 +0000
171+++ modules/Ubuntu/Components/plugin/unixsignalhandler_p.h 2014-03-26 19:26:16 +0000
172@@ -0,0 +1,60 @@
173+/*
174+ * Copyright 2014 Canonical Ltd.
175+ *
176+ * This program is free software; you can redistribute it and/or modify
177+ * it under the terms of the GNU Lesser General Public License as published by
178+ * the Free Software Foundation; version 3.
179+ *
180+ * This program is distributed in the hope that it will be useful,
181+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
182+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
183+ * GNU Lesser General Public License for more details.
184+ *
185+ * You should have received a copy of the GNU Lesser General Public License
186+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
187+ *
188+ */
189+#ifndef UNIXSIGNALHANDLER_P_H
190+#define UNIXSIGNALHANDLER_P_H
191+
192+#include <QtCore/QObject>
193+#include <QtCore/QHash>
194+#include <signal.h>
195+
196+class QSocketNotifier;
197+class UnixSignalHandler : public QObject
198+{
199+ Q_OBJECT
200+public:
201+ enum SignalType {
202+ Invalid = 0,
203+ Interrupt = SIGINT,
204+ Terminate = SIGTERM
205+ };
206+
207+ typedef QPair<int[2], QSocketNotifier*> HandlerType;
208+
209+ static UnixSignalHandler &instance()
210+ {
211+ static UnixSignalHandler instance;
212+ return instance;
213+ }
214+
215+ void connectSignal(SignalType type);
216+
217+Q_SIGNALS:
218+ void signalTriggered(int type);
219+
220+private Q_SLOTS:
221+ void notifierActivated(int socket);
222+private:
223+ explicit UnixSignalHandler(QObject *parent = 0);
224+
225+ static void signalHook(int);
226+ HandlerType createHandler(int signal);
227+
228+ QHash<SignalType, HandlerType> notifiers;
229+ QHash<int, SignalType> socketRegister;
230+};
231+
232+#endif // UNIXSIGNALHANDLER_P_H
233
234=== added file 'tests/unit_x11/tst_statesaver/SimpleApp.qml'
235--- tests/unit_x11/tst_statesaver/SimpleApp.qml 1970-01-01 00:00:00 +0000
236+++ tests/unit_x11/tst_statesaver/SimpleApp.qml 2014-03-26 19:26:16 +0000
237@@ -0,0 +1,28 @@
238+/*
239+ * Copyright 2014 Canonical Ltd.
240+ *
241+ * This program is free software; you can redistribute it and/or modify
242+ * it under the terms of the GNU Lesser General Public License as published by
243+ * the Free Software Foundation; version 3.
244+ *
245+ * This program is distributed in the hope that it will be useful,
246+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
247+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
248+ * GNU Lesser General Public License for more details.
249+ *
250+ * You should have received a copy of the GNU Lesser General Public License
251+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
252+ */
253+
254+import QtQuick 2.0
255+import Ubuntu.Components 0.1
256+
257+Item {
258+ property var boolArray: [false, false]
259+ property var intArray: [1, 2]
260+ property var realArray: [10.1, 20.2]
261+ property var stringArray: ["false", "false"]
262+ id: testItem
263+ objectName: "testItem"
264+ StateSaver.properties: "boolArray, intArray, realArray, stringArray"
265+}
266
267=== modified file 'tests/unit_x11/tst_statesaver/tst_statesaver.cpp'
268--- tests/unit_x11/tst_statesaver/tst_statesaver.cpp 2014-03-26 19:26:15 +0000
269+++ tests/unit_x11/tst_statesaver/tst_statesaver.cpp 2014-03-26 19:26:16 +0000
270@@ -32,6 +32,7 @@
271 #include "ucapplication.h"
272 #include <QtCore/QProcess>
273 #include <QtCore/QProcessEnvironment>
274+#include <signal.h>
275
276 #define protected public
277 #include "ucstatesaver.h"
278@@ -535,6 +536,52 @@
279 QString fileName = stateFile("NormalAppClose");
280 QVERIFY(!QFile(fileName).exists());
281 }
282+
283+ void test_SigTerm()
284+ {
285+ QProcess testApp;
286+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
287+ env.insert("APP_ID", "SimpleApp");
288+ testApp.setProcessEnvironment(env);
289+ testApp.start("qmlscene -I ../../../modules SimpleApp.qml");
290+ testApp.waitForStarted();
291+
292+ // send SIGTERM signal to the process, use terminate() to do that.
293+ testApp.terminate();
294+ testApp.waitForFinished();
295+
296+ QString fileName = stateFile("SimpleApp");
297+ QVERIFY(!QFile(fileName).exists());
298+ }
299+
300+ void test_SigInt()
301+ {
302+ QProcess testApp;
303+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
304+ env.insert("APP_ID", "SimpleApp");
305+ testApp.setProcessEnvironment(env);
306+ testApp.start("qmlscene -I ../../../modules SimpleApp.qml");
307+ testApp.waitForStarted();
308+
309+ QTest::qWait(1000);
310+
311+ // make sure we are not killing the parent
312+ QVERIFY(testApp.pid() != QCoreApplication::applicationPid());
313+ // skip tests if the application PID is zero => the child app PID seems to be zero as well
314+ if (!testApp.pid()) {
315+ // kill child process
316+ testApp.close();
317+ QSKIP("This test requires valid PID");
318+ }
319+ // send SIGINT
320+ ::kill(testApp.pid(), SIGINT);
321+ testApp.waitForFinished();
322+
323+ QString fileName = stateFile("SimpleApp");
324+ QVERIFY(QFile(fileName).exists());
325+ // clean the file
326+ QFile::remove(fileName);
327+ }
328 };
329
330 QTEST_MAIN(tst_StateSaverTest)

Subscribers

People subscribed via source and target branches

to status/vote changes: