Skip to content

Commit

Permalink
Fix thread-unsafe initialization of QgsExpression::Functions()
Browse files Browse the repository at this point in the history
The method initializes the gmFunctions static member, without any mutex protection.
This turned out to cause random crashes in the tests of the WFS provider since the downloader
thread may evaluate an expression, in parallel of the main thread, which does the same.
This was mainly seen on Mac Travis (2 crashes + 1 failures, over 50 iterations), when
parallelizing tests so as to get particular scheduling :
https://travis-ci.org/rouault/Quantum-GIS/builds/121720556.
But I could finally reproduce it systematically on my Linux box when inserting the following sleep.

diff --git a/src/providers/wfs/qgswfsshareddata.cpp b/src/providers/wfs/qgswfsshareddata.cpp
index adc7042..e9e4577 100644
--- a/src/providers/wfs/qgswfsshareddata.cpp
+++ b/src/providers/wfs/qgswfsshareddata.cpp
@@ -426,6 +426,7 @@ int QgsWFSSharedData::registerToCache( QgsWFSFeatureIterator* iterator, QgsRecta
     connect( mDownloader, SIGNAL( ready() ), &loop, SLOT( quit() ) );
     mDownloader->start();
     loop.exec( QEventLoop::ExcludeUserInputEvents );
+    usleep( 100 * 1000 );
   }
   if ( mDownloadFinished )
     return -1;

After applying this commit, the Mac builder is fine:
https://travis-ci.org/rouault/Quantum-GIS/builds/121756158
  • Loading branch information
rouault authored and m-kuhn committed Apr 9, 2016
1 parent d4f62ce commit 510f602
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/core/qgsexpression.cpp
Expand Up @@ -21,6 +21,7 @@
#include <QRegExp>
#include <QColor>
#include <QUuid>
#include <QMutex>

#include <math.h>
#include <limits>
Expand Down Expand Up @@ -2857,6 +2858,13 @@ QList<QgsExpression::Function*> QgsExpression::gmOwnedFunctions;

const QList<QgsExpression::Function*>& QgsExpression::Functions()
{
// The construction of the list isn't thread-safe, and without the mutex,
// crashes in the WFS provider may occur, since it can parse expressions
// in parallel.
// The mutex needs to be recursive.
static QMutex sFunctionsMutex( QMutex::Recursive );
QMutexLocker locker( &sFunctionsMutex );

if ( gmFunctions.isEmpty() )
{
gmFunctions
Expand Down

0 comments on commit 510f602

Please sign in to comment.