Merge lp:~renatofilho/qtorganizer5-eds/fix-1423185 into lp:qtorganizer5-eds

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Bill Filler
Approved revision: 74
Merged at revision: 74
Proposed branch: lp:~renatofilho/qtorganizer5-eds/fix-1423185
Merge into: lp:qtorganizer5-eds
Diff against target: 314 lines (+116/-59)
5 files modified
organizer/qorganizer-eds-engine.cpp (+8/-1)
organizer/qorganizer-eds-engine.h (+3/-0)
organizer/qorganizer-eds-requestdata.cpp (+12/-39)
organizer/qorganizer-eds-requestdata.h (+4/-6)
tests/unittest/cancel-operation-test.cpp (+89/-13)
To merge this branch: bzr merge lp:~renatofilho/qtorganizer5-eds/fix-1423185
Reviewer Review Type Date Requested Status
Alan Pope 🍺🐧🐱 πŸ¦„ (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+252184@code.launchpad.net

Commit message

Fixed engine crash while destroying and requests still running.

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
Alan Pope 🍺🐧🐱 πŸ¦„ (popey) wrote :

I've been unable to crash the app with this patch on my Nexus 7. Thanks Renato!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'organizer/qorganizer-eds-engine.cpp'
2--- organizer/qorganizer-eds-engine.cpp 2015-02-26 17:30:35 +0000
3+++ organizer/qorganizer-eds-engine.cpp 2015-03-06 22:48:43 +0000
4@@ -98,6 +98,7 @@
5 {
6 while(m_runningRequests.count()) {
7 QOrganizerAbstractRequest *req = m_runningRequests.keys().first();
8+ req->cancel();
9 QOrganizerEDSEngine::requestDestroyed(req);
10 }
11
12@@ -624,7 +625,7 @@
13 &uids,
14 &gError);
15 if (gError) {
16- qWarning() << "Fail to create items:" << gError->message;
17+ qWarning() << "Fail to create items:" << (void*) data << gError->message;
18 g_error_free(gError);
19 gError = 0;
20
21@@ -1073,6 +1074,7 @@
22 data->cancel();
23 return true;
24 }
25+ qWarning() << "Request is not running" << (void*) req;
26 return false;
27 }
28
29@@ -1178,6 +1180,11 @@
30 << QOrganizerItemType::TypeTodoOccurrence;
31 }
32
33+int QOrganizerEDSEngine::runningRequestCount() const
34+{
35+ return m_runningRequests.count();
36+}
37+
38 void QOrganizerEDSEngine::onSourceAdded(const QString &collectionId)
39 {
40 d->watch(collectionId);
41
42=== modified file 'organizer/qorganizer-eds-engine.h'
43--- organizer/qorganizer-eds-engine.h 2014-05-24 21:09:00 +0000
44+++ organizer/qorganizer-eds-engine.h 2015-03-06 22:48:43 +0000
45@@ -125,6 +125,9 @@
46 virtual QList<QtOrganizer::QOrganizerItemDetail::DetailType> supportedItemDetails(QtOrganizer::QOrganizerItemType::ItemType itemType) const;
47 virtual QList<QtOrganizer::QOrganizerItemType::ItemType> supportedItemTypes() const;
48
49+ // debug
50+ int runningRequestCount() const;
51+
52 protected Q_SLOTS:
53 void onSourceAdded(const QString &collectionId);
54 void onSourceRemoved(const QString &collectionId);
55
56=== modified file 'organizer/qorganizer-eds-requestdata.cpp'
57--- organizer/qorganizer-eds-requestdata.cpp 2014-10-01 13:45:34 +0000
58+++ organizer/qorganizer-eds-requestdata.cpp 2015-03-06 22:48:43 +0000
59@@ -71,24 +71,13 @@
60
61 void RequestData::cancel()
62 {
63- QMutexLocker locker(&m_canceling);
64 if (m_cancellable) {
65- GCancellable *cancellable = m_cancellable;
66- gulong id = g_cancellable_connect(cancellable,
67- (GCallback) RequestData::onCancelled,
68- this, NULL);
69-
70-
71- // cancel
72- g_cancellable_cancel(cancellable);
73-
74- // wait the cancel
75- if (cancellable) {
76- wait();
77- }
78-
79- // done
80- g_cancellable_disconnect(cancellable, id);
81+ g_cancellable_cancel(m_cancellable);
82+ }
83+
84+ if (isLive()) {
85+ finish(QOrganizerManager::UnspecifiedError,
86+ QOrganizerAbstractRequest::CanceledState);
87 }
88 }
89
90@@ -110,42 +99,26 @@
91 return result;
92 }
93
94-bool RequestData::isCanceling()
95-{
96- bool result = true;
97- if (m_canceling.tryLock()) {
98- result = false;
99- m_canceling.unlock();
100- }
101- return result;
102-}
103-
104 void RequestData::deleteLater()
105 {
106- if (isWaiting() || isCanceling()) {
107+ if (isWaiting()) {
108 // still running
109 return;
110 }
111- m_parent->m_runningRequests.remove(m_req);
112+ if (!m_parent.isNull()) {
113+ m_parent->m_runningRequests.remove(m_req);
114+ }
115 delete this;
116 }
117
118-void RequestData::finish(QOrganizerManager::Error error, QtOrganizer::QOrganizerAbstractRequest::State state)
119+void RequestData::finish(QOrganizerManager::Error error,
120+ QtOrganizer::QOrganizerAbstractRequest::State state)
121 {
122 Q_UNUSED(error);
123 Q_UNUSED(state);
124 m_finished = true;
125 }
126
127-void RequestData::onCancelled(GCancellable *cancellable, RequestData *self)
128-{
129- Q_UNUSED(cancellable);
130- if (self->m_req) {
131- self->finish(QOrganizerManager::UnspecifiedError, QOrganizerAbstractRequest::CanceledState);
132- }
133- self->m_cancellable = 0;
134-}
135-
136 void RequestData::setClient(EClient *client)
137 {
138 if (m_client == client) {
139
140=== modified file 'organizer/qorganizer-eds-requestdata.h'
141--- organizer/qorganizer-eds-requestdata.h 2014-05-25 19:46:49 +0000
142+++ organizer/qorganizer-eds-requestdata.h 2015-03-06 22:48:43 +0000
143@@ -44,7 +44,6 @@
144 virtual void finish(QtOrganizer::QOrganizerManager::Error error, QtOrganizer::QOrganizerAbstractRequest::State state) = 0;
145 void wait();
146 bool isWaiting();
147- bool isCanceling();
148
149 template<class T>
150 T* request() const {
151@@ -53,15 +52,16 @@
152
153 template<class T>
154 void emitChangeset(T *cs) {
155- m_parent->d->emitSharedSignals<T>(cs);
156+ if (!m_parent.isNull()) {
157+ m_parent->d->emitSharedSignals<T>(cs);
158+ }
159 }
160
161 protected:
162- QOrganizerEDSEngine *m_parent;
163+ QPointer<QOrganizerEDSEngine> m_parent;
164 EClient *m_client;
165 QtOrganizer::QOrganizerItemChangeSet m_changeSet;
166 QMutex m_waiting;
167- QMutex m_canceling;
168 bool m_finished;
169
170 virtual ~RequestData();
171@@ -69,8 +69,6 @@
172 private:
173 QPointer<QtOrganizer::QOrganizerAbstractRequest> m_req;
174 GCancellable *m_cancellable;
175-
176- static void onCancelled(GCancellable *cancellable, RequestData *self);
177 };
178
179 #endif
180
181=== modified file 'tests/unittest/cancel-operation-test.cpp'
182--- tests/unittest/cancel-operation-test.cpp 2014-10-06 14:07:54 +0000
183+++ tests/unittest/cancel-operation-test.cpp 2015-03-06 22:48:43 +0000
184@@ -40,8 +40,9 @@
185 void init()
186 {
187 EDSBaseTest::init();
188-
189- m_engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
190+ QMap<QString, QString> parameters;
191+ parameters.insert("sleepMode", "true");
192+ m_engine = QOrganizerEDSEngine::createEDSEngine(parameters);
193
194 QtOrganizer::QOrganizerManager::Error error;
195 m_collection = QOrganizerCollection();
196@@ -59,20 +60,17 @@
197 EDSBaseTest::cleanup();
198 }
199
200- void cancelOperationBeforeStart()
201+ void cancelOperationAfterStart()
202 {
203- // initial collections
204- QList<QOrganizerCollection> collections = m_engine->collections(0);
205- int initialCollectionsCount = collections.count();
206-
207 QOrganizerEvent event;
208 event.setStartDateTime(QDateTime::currentDateTime());
209 event.setDisplayLabel("displayLabelValue");
210 event.setDescription("descriptionValue");
211 event.setCollectionId(m_collection.id());
212
213+ QSignalSpy createdItem(m_engine, SIGNAL(itemsAdded(QList<QOrganizerItemId>)));
214+
215 // Try cancel a create item operation
216- QSignalSpy createdItem(m_engine, SIGNAL(itemsAdded(QList<QOrganizerItemId>)));
217 QOrganizerItemSaveRequest req;
218 req.setItem(event);
219 m_engine->startRequest(&req);
220@@ -81,11 +79,89 @@
221 QCOMPARE(req.state(), QOrganizerAbstractRequest::CanceledState);
222 QTRY_COMPARE(createdItem.count(), 0);
223
224- // check if collection was not create
225- collections = m_engine->collections(0);
226- QCOMPARE(collections.count(), initialCollectionsCount);
227- }
228-
229+ QTRY_COMPARE(m_engine->runningRequestCount(), 0);
230+ }
231+
232+ void deleteManagerBeforeRequestFinish()
233+ {
234+ QOrganizerEvent event;
235+ event.setStartDateTime(QDateTime::currentDateTime());
236+ event.setDisplayLabel("displayLabelValue");
237+ event.setDescription("descriptionValue");
238+ event.setCollectionId(m_collection.id());
239+
240+ QOrganizerEDSEngine *engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
241+
242+ // Start a request
243+ QOrganizerItemSaveRequest req;
244+ req.setItem(event);
245+ engine->startRequest(&req);
246+ QCOMPARE(req.state(), QOrganizerAbstractRequest::ActiveState);
247+
248+ // delete engine
249+ delete engine;
250+ }
251+
252+ void cancelBeforeStart()
253+ {
254+ QOrganizerEvent event;
255+ event.setStartDateTime(QDateTime::currentDateTime());
256+ event.setDisplayLabel("displayLabelValue");
257+ event.setDescription("descriptionValue");
258+ event.setCollectionId(m_collection.id());
259+
260+ // Cancel before start
261+ QOrganizerItemSaveRequest req;
262+ req.setItem(event);
263+ m_engine->cancelRequest(&req);
264+
265+ QTRY_COMPARE(m_engine->runningRequestCount(), 0);
266+ }
267+
268+ void destroyRequestAfterStart()
269+ {
270+ QOrganizerEvent event;
271+ event.setStartDateTime(QDateTime::currentDateTime());
272+ event.setDisplayLabel("displayLabelValue");
273+ event.setDescription("descriptionValue");
274+ event.setCollectionId(m_collection.id());
275+
276+ QOrganizerManager *mgr = new QOrganizerManager("eds");
277+ QOrganizerItemSaveRequest *req = new QOrganizerItemSaveRequest;
278+ req->setManager(mgr);
279+ req->setItem(event);
280+ req->start();
281+ req->deleteLater();
282+
283+ delete mgr;
284+ }
285+
286+ void startMultipleRequests()
287+ {
288+ QList<QOrganizerCollection> collections = m_engine->collections(0);
289+
290+ QList<QOrganizerItemSaveRequest*> requests;
291+ for(int i=0; i < 100; i++) {
292+ QOrganizerEvent event;
293+ event.setStartDateTime(QDateTime::currentDateTime());
294+ event.setDisplayLabel(QString("displayLabelValue_%1").arg(i));
295+ event.setDescription(QString("descriptionValue_%2").arg(i));
296+ event.setCollectionId(m_collection.id());
297+
298+ QOrganizerItemSaveRequest *req = new QOrganizerItemSaveRequest;
299+ req->setItem(event);
300+ m_engine->startRequest(req);
301+ QCOMPARE(req->state(), QOrganizerAbstractRequest::ActiveState);
302+ requests << req;
303+ }
304+
305+ Q_FOREACH(QOrganizerItemSaveRequest *r, requests) {
306+ m_engine->cancelRequest(r);
307+ QCOMPARE(r->state(), QOrganizerAbstractRequest::CanceledState);
308+ }
309+
310+ QTRY_COMPARE(m_engine->runningRequestCount(), 0);
311+ }
312 };
313
314 QTEST_MAIN(CancelOperationTest)

Subscribers

People subscribed via source and target branches