Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix stuck tasks when proxied task using a proxy progress task
completes before the proxy task has been started by task manager

Fixes #21589, fixes #19761

(cherry picked from commit b28227f)
  • Loading branch information
nyalldawson committed Apr 2, 2019
1 parent be04bdc commit e300042
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/core/qgsproxyprogresstask.cpp
Expand Up @@ -25,14 +25,20 @@ QgsProxyProgressTask::QgsProxyProgressTask( const QString &description )

void QgsProxyProgressTask::finalize( bool result )
{
QMutexLocker lock( &mNotFinishedMutex );
mAlreadyFinished = true;

mResult = result;
mNotFinishedWaitCondition.wakeAll();
}

bool QgsProxyProgressTask::run()
{
mNotFinishedMutex.lock();
mNotFinishedWaitCondition.wait( &mNotFinishedMutex );
if ( !mAlreadyFinished )
{
mNotFinishedWaitCondition.wait( &mNotFinishedMutex );
}
mNotFinishedMutex.unlock();

return mResult;
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsproxyprogresstask.h
Expand Up @@ -64,6 +64,7 @@ class CORE_EXPORT QgsProxyProgressTask : public QgsTask

QWaitCondition mNotFinishedWaitCondition;
QMutex mNotFinishedMutex;
bool mAlreadyFinished = false;
bool mResult = true;

};
Expand Down
74 changes: 74 additions & 0 deletions tests/src/core/testqgstaskmanager.cpp
Expand Up @@ -19,6 +19,7 @@
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsapplication.h"
#include "qgsproxyprogresstask.h"
#include <QObject>
#include "qgstest.h"

Expand Down Expand Up @@ -270,6 +271,9 @@ class TestQgsTaskManager : public QObject
void managerWithSubTasks2();
void managerWithSubTasks3();
void cancelBeforeStart();
void proxyTask();
void proxyTask2();
void scopedProxyTask();
};

void TestQgsTaskManager::initTestCase()
Expand Down Expand Up @@ -1374,5 +1378,75 @@ void TestQgsTaskManager::cancelBeforeStart()
flushEvents();
}

void TestQgsTaskManager::proxyTask()
{
if ( QgsTest::isTravis() )
QSKIP( "This test is disabled on Travis CI environment" );

QgsProxyProgressTask *proxyTask = new QgsProxyProgressTask( QString() );

// finalize before task gets a chance to start
QgsTaskManager manager;
proxyTask->finalize( false );
QPointer< QgsTask > p( proxyTask );

manager.addTask( proxyTask );

// should all be ok, no deadlock...
while ( p )
{
QCoreApplication::processEvents();
}
flushEvents();
}

void TestQgsTaskManager::proxyTask2()
{
if ( QgsTest::isTravis() )
QSKIP( "This test is disabled on Travis CI environment" );

QgsProxyProgressTask *proxyTask = new QgsProxyProgressTask( QString() );

// finalize before task gets a chance to start
QgsTaskManager manager;
QPointer< QgsTask > p( proxyTask );
manager.addTask( proxyTask );

// should all be ok, no deadlock...
while ( proxyTask->status() != QgsTask::Running )
{
QCoreApplication::processEvents();
}
proxyTask->finalize( false );
while ( p )
{
QCoreApplication::processEvents();
}

flushEvents();
}

void TestQgsTaskManager::scopedProxyTask()
{
if ( QgsTest::isTravis() )
QSKIP( "This test is disabled on Travis CI environment" );

{
// task finishes before it can start
QgsScopedProxyProgressTask task{ QString() };
}

// should all be ok, no deadlock...
while ( QgsApplication::taskManager()->countActiveTasks() == 0 )
{
QCoreApplication::processEvents();
}
while ( QgsApplication::taskManager()->countActiveTasks() > 0 )
{
QCoreApplication::processEvents();
}
flushEvents();
}

QGSTEST_MAIN( TestQgsTaskManager )
#include "testqgstaskmanager.moc"

0 comments on commit e300042

Please sign in to comment.