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