@@ -46,6 +46,7 @@ class TestQgsOgrProvider : public QObject
46
46
47
47
void setupProxy ();
48
48
void decodeUri ();
49
+ void testThread ();
49
50
50
51
private:
51
52
QString mTestDataDir ;
@@ -130,5 +131,88 @@ void TestQgsOgrProvider::decodeUri()
130
131
QCOMPARE ( parts.value ( QStringLiteral ( " layerName" ) ).toString (), QString ( " a_layer" ) );
131
132
}
132
133
134
+
135
+ class ReadVectorLayer : public QThread
136
+ {
137
+
138
+ public :
139
+ ReadVectorLayer ( const QString &filePath, QMutex &mutex, QWaitCondition &waitForVlCreation, QWaitCondition &waitForProcessEvents )
140
+ : _filePath( filePath ), _mutex( mutex ), _waitForVlCreation( waitForVlCreation ), _waitForProcessEvents( waitForProcessEvents ) {}
141
+
142
+ void run () override
143
+ {
144
+
145
+ QgsVectorLayer *vl2 = new QgsVectorLayer ( _filePath, QStringLiteral ( " thread_test" ), QLatin1Literal ( " ogr" ) );
146
+
147
+ QgsFeature f;
148
+ QVERIFY ( vl2->getFeatures ().nextFeature ( f ) );
149
+
150
+ _mutex.lock ();
151
+ _waitForVlCreation.wakeAll ();
152
+ _mutex.unlock ();
153
+
154
+ _mutex.lock ();
155
+ _waitForProcessEvents.wait ( &_mutex );
156
+ _mutex.unlock ();
157
+
158
+ delete vl2;
159
+ }
160
+
161
+ private:
162
+ QString _filePath;
163
+ QMutex &_mutex;
164
+ QWaitCondition &_waitForVlCreation;
165
+ QWaitCondition &_waitForProcessEvents;
166
+
167
+ };
168
+
169
+ void failOnWarning ( QtMsgType type, const QMessageLogContext &context, const QString &msg )
170
+ {
171
+ Q_UNUSED ( context );
172
+
173
+ switch ( type )
174
+ {
175
+ case QtWarningMsg:
176
+ QFAIL ( QString ( " No Qt warning message expect : %1" ).arg ( msg ).toUtf8 () );
177
+ default :;
178
+ }
179
+ }
180
+
181
+ void TestQgsOgrProvider::testThread ()
182
+ {
183
+ // After reading a QgsVectorLayer (getFeatures) from another thread the QgsOgrConnPoolGroup starts
184
+ // an expiration timer. The timer belongs to the main thread in order to listening the event
185
+ // loop and is parented to its QgsOgrConnPoolGroup. So when we delete the QgsVectorLayer, the
186
+ // QgsConnPoolGroup and the timer are subsequently deleted from another thread. This leads to
187
+ // segfault later when the expiration time reaches its timeout.
188
+
189
+ QMutex mutex;
190
+ QWaitCondition waitForVlCreation;
191
+ QWaitCondition waitForProcessEvents;
192
+
193
+ QString filePath = mTestDataDir + ' /' + QStringLiteral ( " lines.shp" );
194
+ QThread *thread = new ReadVectorLayer ( filePath, mutex, waitForVlCreation, waitForProcessEvents );
195
+
196
+ thread->start ();
197
+
198
+ mutex.lock ();
199
+ waitForVlCreation.wait ( &mutex );
200
+ mutex.unlock ();
201
+
202
+ // make sure timer as been started
203
+ QCoreApplication::processEvents ();
204
+
205
+ qInstallMessageHandler ( failOnWarning );
206
+
207
+ mutex.lock ();
208
+ waitForProcessEvents.wakeAll ();
209
+ mutex.unlock ();
210
+
211
+ thread->wait ();
212
+ qInstallMessageHandler ( 0 );
213
+
214
+ }
215
+
216
+
133
217
QGSTEST_MAIN ( TestQgsOgrProvider )
134
218
#include " testqgsogrprovider.moc"
0 commit comments