Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[wfs] Fix some race conditions
(cherry picked from commit 2041cad)
  • Loading branch information
nyalldawson committed Sep 6, 2018
1 parent bf10aca commit 8a5bcf9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 20 deletions.
34 changes: 23 additions & 11 deletions src/providers/wfs/qgswfsrequest.cpp
Expand Up @@ -130,13 +130,15 @@ bool QgsWfsRequest::sendGET( const QUrl &url, bool synchronous, bool forceRefres

QWaitCondition waitCondition;
QMutex waitConditionMutex;
bool threadFinished = false;
bool success = false;

std::function<bool()> downloaderFunction = [ this, request, synchronous, &waitConditionMutex, &waitCondition ]()
std::function<void()> downloaderFunction = [ this, request, synchronous, &waitConditionMutex, &waitCondition, &threadFinished, &success ]()
{
if ( QThread::currentThread() != QgsApplication::instance()->thread() )
QgsNetworkAccessManager::instance( Qt::DirectConnection );

bool success = true;
success = true;
mReply = QgsNetworkAccessManager::instance()->get( request );

mReply->setReadBufferSize( READ_BUFFER_SIZE_HINT );
Expand Down Expand Up @@ -180,41 +182,51 @@ bool QgsWfsRequest::sendGET( const QUrl &url, bool synchronous, bool forceRefres
loop.exec();
}
}
waitConditionMutex.lock();
threadFinished = true;
waitCondition.wakeAll();
return success;
waitConditionMutex.unlock();
};

bool success;

if ( synchronous && QThread::currentThread() == QApplication::instance()->thread() )
{
std::unique_ptr<DownloaderThread> downloaderThread = qgis::make_unique<DownloaderThread>( downloaderFunction );
downloaderThread->start();

while ( !downloaderThread->isFinished() )
while ( true )
{
waitConditionMutex.lock();
if ( threadFinished )
{
waitConditionMutex.unlock();
break;
}
waitCondition.wait( &waitConditionMutex );
waitConditionMutex.unlock();

// If the downloader thread wakes us (the main thread) up and is not yet finished
// he needs the authentication to run.
// The processEvents() call gives the auth manager the chance to show a dialog and
// once done with that, we can wake the downloaderThread again and continue the download.
if ( !downloaderThread->isFinished() )
if ( !threadFinished )
{
waitConditionMutex.unlock();

QgsApplication::instance()->processEvents();
waitConditionMutex.lock();
waitCondition.wakeAll();
waitConditionMutex.unlock();
}
else
{
waitConditionMutex.unlock();
}
}

success = downloaderThread->success();
// wait for thread to gracefully exit
downloaderThread->wait();
}
else
{
success = downloaderFunction();
downloaderFunction();
}
return success && mErrorMessage.isEmpty();
}
Expand Down
12 changes: 3 additions & 9 deletions src/providers/wfs/qgswfsrequest.h
Expand Up @@ -124,25 +124,19 @@ class DownloaderThread : public QThread
Q_OBJECT

public:
DownloaderThread( std::function<bool()> function, QObject *parent = nullptr )
DownloaderThread( std::function<void()> function, QObject *parent = nullptr )
: QThread( parent )
, mFunction( function )
{
}

void run() override
{
mSuccess = mFunction();
}

bool success() const
{
return mSuccess;
mFunction();
}

private:
std::function<bool()> mFunction;
bool mSuccess = false;
std::function<void()> mFunction;
};

#endif // QGSWFSREQUEST_H

0 comments on commit 8a5bcf9

Please sign in to comment.