Skip to content

Commit d683550

Browse files
committed
Fix crash when tasks are canceled before starting
Avoids an attempt to unlock an already unlocked mutex, which causes a crash. Should fix a number of crash report tickets...
1 parent 123f694 commit d683550

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

src/core/qgstaskmanager.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ QgsTask::QgsTask( const QString &name, Flags flags )
3434
QgsTask::~QgsTask()
3535
{
3636
Q_ASSERT_X( mStatus != Running, "delete", QStringLiteral( "status was %1" ).arg( mStatus ).toLatin1() );
37-
37+
mNotFinishedMutex.tryLock(); // we're not guaranteed to already have the lock in place here
3838
Q_FOREACH ( const SubTask &subTask, mSubTasks )
3939
{
4040
delete subTask.task;
4141
}
42+
mNotFinishedMutex.unlock();
4243
}
4344

4445
qint64 QgsTask::elapsedTime() const
@@ -261,6 +262,7 @@ void QgsTask::processSubTasksForCompletion()
261262
setProgress( 100.0 );
262263
emit statusChanged( Complete );
263264
emit taskCompleted();
265+
mNotFinishedMutex.tryLock(); // we're not guaranteed to already have the lock in place here
264266
mNotFinishedMutex.unlock();
265267
}
266268
else if ( mStatus == Complete )
@@ -288,6 +290,7 @@ void QgsTask::processSubTasksForTermination()
288290

289291
emit statusChanged( Terminated );
290292
emit taskTerminated();
293+
mNotFinishedMutex.tryLock(); // we're not guaranteed to already have the lock in place here
291294
mNotFinishedMutex.unlock();
292295
}
293296
else if ( mStatus == Terminated && !subTasksTerminated )

tests/src/core/testqgstaskmanager.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ class TestQgsTaskManager : public QObject
269269
void managerWithSubTasks();
270270
void managerWithSubTasks2();
271271
void managerWithSubTasks3();
272+
void cancelBeforeStart();
272273
};
273274

274275
void TestQgsTaskManager::initTestCase()
@@ -1348,5 +1349,30 @@ void TestQgsTaskManager::managerWithSubTasks3()
13481349
QCOMPARE( manager3.dependencies( subTask2Id ), QSet< long >() );
13491350
}
13501351

1352+
void TestQgsTaskManager::cancelBeforeStart()
1353+
{
1354+
// add a lot of tasks to the manager, so that some are queued and can't start immediately
1355+
// then cancel them all!
1356+
QList< QgsTask * > tasks;
1357+
QgsTaskManager manager;
1358+
for ( int i = 0; i < 30; ++i )
1359+
{
1360+
QgsTask *task = new CancelableTask();
1361+
tasks << task;
1362+
manager.addTask( task );
1363+
}
1364+
1365+
for ( QgsTask *t : qgis::as_const( tasks ) )
1366+
{
1367+
t->cancel();
1368+
}
1369+
1370+
while ( manager.countActiveTasks() > 1 )
1371+
{
1372+
QCoreApplication::processEvents();
1373+
}
1374+
flushEvents();
1375+
}
1376+
13511377
QGSTEST_MAIN( TestQgsTaskManager )
13521378
#include "testqgstaskmanager.moc"

0 commit comments

Comments
 (0)