Merge lp:~zsombi/ubuntu-ui-toolkit/alarmmodel-get-crash into lp:ubuntu-ui-toolkit/staging

Proposed by Zsombor Egri
Status: Merged
Approved by: Cris Dywan
Approved revision: 1457
Merged at revision: 1457
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/alarmmodel-get-crash
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 225 lines (+115/-12)
6 files modified
modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp (+6/-7)
modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h (+5/-3)
modules/Ubuntu/Components/plugin/ucalarm_p.h (+1/-0)
modules/Ubuntu/Components/plugin/ucalarmmodel.cpp (+9/-1)
tests/unit_x11/tst_components/tst_components.pro (+2/-1)
tests/unit_x11/tst_components/tst_stress_alarmmodel.qml (+92/-0)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/alarmmodel-get-crash
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Cris Dywan Approve
Nekhelesh Ramananthan (community) testing Approve
Review via email: mp+253981@code.launchpad.net

Commit message

Fixing crashes when AlarmModel::get() returned valid stock alarm ends up to be NULL in QML.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

Tested on vivid desktop where without this MP, the clock app crashes pretty much every time while using the clock app. With this MP after 15-20 times, not a single crash was reproducible. This MP seems to have done the trick.

review: Approve (testing)
Revision history for this message
Cris Dywan (kalikiana) wrote :

Looks sensible.

FTR I can't reproduce crashes but I get errors with staging
qml: [CLOCK] Error saving alarm, code: 2
file:///usr/share/ubuntu-clock-app/common/AnalogClockMarker.qml:40: TypeError: Cannot read property of null
And this by the looks of it is garbage collection at work.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp'
2--- modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp 2015-02-26 15:09:23 +0000
3+++ modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp 2015-03-24 16:52:43 +0000
4@@ -292,6 +292,12 @@
5 }
6 }
7
8+void AlarmDataAdapter::copyAlarmData(const UCAlarm &other)
9+{
10+ AlarmDataAdapter *pOther = static_cast<AlarmDataAdapter*>(AlarmDataAdapter::get(&other));
11+ setData(pOther->data());
12+}
13+
14 void AlarmDataAdapter::adjustDowSettings(UCAlarm::AlarmType type, UCAlarm::DaysOfWeek days)
15 {
16 QOrganizerItemRecurrence old = event.detail(QOrganizerItemDetail::TypeRecurrence);
17@@ -369,13 +375,6 @@
18 }
19 }
20
21-void AlarmDataAdapter::copyData(const UCAlarm &other)
22-{
23- AlarmDataAdapter *pOther = static_cast<AlarmDataAdapter*>(AlarmDataAdapter::get(&other));
24- setData(pOther->data());
25-}
26-
27-
28 /*-----------------------------------------------------------------------------
29 * Adaptation layer for Alarms.
30 */
31
32=== modified file 'modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h'
33--- modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h 2015-02-26 15:09:23 +0000
34+++ modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h 2015-03-24 16:52:43 +0000
35@@ -58,6 +58,7 @@
36 bool wait(int msec);
37 void completeSave();
38 void completeCancel();
39+ void copyAlarmData(const UCAlarm &other);
40
41 // adaptation specific data
42 void adjustDowSettings(UCAlarm::AlarmType type, UCAlarm::DaysOfWeek days);
43@@ -69,7 +70,6 @@
44 return event;
45 }
46 void setData(const QOrganizerTodo &data);
47- void copyData(const UCAlarm &other);
48
49 protected:
50 QOrganizerTodo event;
51@@ -108,7 +108,7 @@
52 UCAlarm *oldAlarm = takeAt(index);
53 // copy the other alarm data
54 AlarmDataAdapter *pAlarm = static_cast<AlarmDataAdapter*>(AlarmDataAdapter::get(oldAlarm));
55- pAlarm->copyData(alarm);
56+ pAlarm->copyAlarmData(alarm);
57 // and insert it back
58 QDateTime dt = oldAlarm->date();
59 QOrganizerItemId id = oldAlarm->cookie().value<QOrganizerItemId>();
60@@ -123,7 +123,7 @@
61 QOrganizerItemId id = alarm.cookie().value<QOrganizerItemId>();
62 idHash.insert(id, dt);
63 UCAlarm *newAlarm = new UCAlarm;
64- static_cast<AlarmDataAdapter*>(AlarmDataAdapter::get(newAlarm))->copyData(alarm);
65+ UCAlarmPrivate::get(newAlarm)->copyAlarmData(alarm);
66 data.insert(QPair<QDateTime, QOrganizerItemId>(dt, id), newAlarm);
67 return indexOf(id);
68 }
69@@ -140,6 +140,8 @@
70 UCAlarm *alarm = takeAt(index);
71 delete alarm;
72 }
73+
74+protected:
75 // removes alarm data at index and returns the alarm pointer
76 UCAlarm *takeAt(int index)
77 {
78
79=== modified file 'modules/Ubuntu/Components/plugin/ucalarm_p.h'
80--- modules/Ubuntu/Components/plugin/ucalarm_p.h 2014-12-02 11:21:22 +0000
81+++ modules/Ubuntu/Components/plugin/ucalarm_p.h 2015-03-24 16:52:43 +0000
82@@ -59,6 +59,7 @@
83 virtual void reset() = 0;
84 virtual void completeSave() = 0;
85 virtual void completeCancel() = 0;
86+ virtual void copyAlarmData(const UCAlarm &other) = 0;
87
88 // common privates
89 UCAlarm *q_ptr;
90
91=== modified file 'modules/Ubuntu/Components/plugin/ucalarmmodel.cpp'
92--- modules/Ubuntu/Components/plugin/ucalarmmodel.cpp 2015-03-03 13:47:48 +0000
93+++ modules/Ubuntu/Components/plugin/ucalarmmodel.cpp 2015-03-24 16:52:43 +0000
94@@ -22,6 +22,7 @@
95 #include "alarmmanager_p.h"
96 #include <QtQml/QQmlPropertyMap>
97 #include <QtQml/QQmlInfo>
98+#include <QtQml/QQmlEngine>
99
100 /*!
101 * \qmltype AlarmModel
102@@ -213,7 +214,14 @@
103 */
104 UCAlarm* UCAlarmModel::get(int index)
105 {
106- return AlarmManager::instance().alarmAt(index);
107+ UCAlarm *alarm = AlarmManager::instance().alarmAt(index);
108+ if (alarm) {
109+ UCAlarm *tempAlarm = new UCAlarm(this);
110+ UCAlarmPrivate::get(tempAlarm)->copyAlarmData(*alarm);
111+ alarm = tempAlarm;
112+ QQmlEngine::setObjectOwnership(tempAlarm, QQmlEngine::JavaScriptOwnership);
113+ }
114+ return alarm;
115 }
116
117 /*!
118
119=== modified file 'tests/unit_x11/tst_components/tst_components.pro'
120--- tests/unit_x11/tst_components/tst_components.pro 2014-08-01 15:26:23 +0000
121+++ tests/unit_x11/tst_components/tst_components.pro 2015-03-24 16:52:43 +0000
122@@ -7,4 +7,5 @@
123 SOURCES += tst_components.cpp tabsmodel.cpp
124 HEADERS += tabsmodel.h
125
126-OTHER_FILES += $$system(ls *.qml)
127+OTHER_FILES += $$system(ls *.qml) \
128+ tst_stress_alarmmodel.qml
129
130=== added file 'tests/unit_x11/tst_components/tst_stress_alarmmodel.qml'
131--- tests/unit_x11/tst_components/tst_stress_alarmmodel.qml 1970-01-01 00:00:00 +0000
132+++ tests/unit_x11/tst_components/tst_stress_alarmmodel.qml 2015-03-24 16:52:43 +0000
133@@ -0,0 +1,92 @@
134+/*
135+ * Copyright 2013 Canonical Ltd.
136+ *
137+ * This program is free software; you can redistribute it and/or modify
138+ * it under the terms of the GNU Lesser General Public License as published by
139+ * the Free Software Foundation; version 3.
140+ *
141+ * This program is distributed in the hope that it will be useful,
142+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
143+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144+ * GNU Lesser General Public License for more details.
145+ *
146+ * You should have received a copy of the GNU Lesser General Public License
147+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
148+ */
149+
150+import QtQuick 2.0
151+import QtTest 1.0
152+import Ubuntu.Test 1.0
153+import Ubuntu.Components 1.2
154+
155+MainView {
156+ width: units.gu(40)
157+ height: units.gu(71)
158+
159+ AlarmModel {
160+ id: model
161+ }
162+
163+ Alarm {
164+ id: testAlarm
165+ }
166+
167+ UbuntuTestCase {
168+ name: "AlarmModelStressTest"
169+ when: windowShown
170+
171+ SignalSpy {
172+ id: modelSpy
173+ signalName: "modelReset"
174+ target: model
175+ }
176+
177+ property string testAlarmMessage: "test_"
178+
179+ function createAlarm(pattern, idx) {
180+ testAlarm.reset();
181+ testAlarm.message = pattern + idx;
182+ var dt = new Date();
183+ dt.setMinutes(dt.getMinutes() + 10);
184+ testAlarm.date = dt;
185+ modelSpy.signalName = "rowsInserted";
186+ testAlarm.save();
187+ modelSpy.wait();
188+ }
189+
190+ function clearTestAlarms(pattern) {
191+ var i = 0;
192+ modelSpy.signalName = "rowsRemoved";
193+ while (i < model.count) {
194+ var alarm = model.get(i);
195+ // this will fail if get() returns NULL
196+ if (alarm.message.indexOf(pattern) == 0) {
197+ alarm.cancel();
198+ modelSpy.wait();
199+ modelSpy.clear();
200+ i = 0;
201+ } else {
202+ i++;
203+ }
204+ }
205+ }
206+
207+ // need to create a huge amount of alarms then cleanone part of it
208+ function initTestCase() {
209+ for (var i = 0; i < 20; i++) {
210+ createAlarm(testAlarmMessage, i)
211+ }
212+ for (var i = 0; i < 40; i++) {
213+ createAlarm("testAlarm_", i)
214+ }
215+ }
216+ function cleanupTestCase() {
217+ clearTestAlarms(testAlarmMessage);
218+ }
219+
220+ function test_remove_alarms()
221+ {
222+ clearTestAlarms("testAlarm_");
223+ }
224+ }
225+}

Subscribers

People subscribed via source and target branches