Skip to content

Commit e948120

Browse files
troopa81nyalldawson
authored andcommitted
Correct crash when read from ogr file in thread (QgsProcessing for instance)
fixes #20581
1 parent 3b4def8 commit e948120

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed

src/providers/ogr/qgsogrconnpool.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn *, QgsOgrConnPoolGrou
156156

157157
if ( it.value()->unref() )
158158
{
159-
delete it.value();
159+
it.value()->deleteLater();
160160
mGroups.erase( it );
161161
}
162162
mMutex.unlock();

tests/src/providers/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ TARGET_LINK_LIBRARIES(qgis_arcgisrestutilstest arcgisfeatureserverprovider_a)
7272

7373
ADD_QGIS_TEST(gdalprovidertest testqgsgdalprovider.cpp)
7474

75+
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
7576
ADD_QGIS_TEST(ogrprovidertest testqgsogrprovider.cpp)
7677

7778
ADD_QGIS_TEST(wmscapabilitiestest

tests/src/providers/testqgsogrprovider.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class TestQgsOgrProvider : public QObject
4646

4747
void setupProxy();
4848
void decodeUri();
49+
void testThread();
4950

5051
private:
5152
QString mTestDataDir;
@@ -130,5 +131,88 @@ void TestQgsOgrProvider::decodeUri()
130131
QCOMPARE( parts.value( QStringLiteral( "layerName" ) ).toString(), QString( "a_layer" ) );
131132
}
132133

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+
133217
QGSTEST_MAIN( TestQgsOgrProvider )
134218
#include "testqgsogrprovider.moc"

0 commit comments

Comments
 (0)