Skip to content

Commit

Permalink
Fix unsafe access of map layer from background thread while running l…
Browse files Browse the repository at this point in the history
…abel engine
  • Loading branch information
nyalldawson committed Jun 28, 2021
1 parent 849819c commit 731810c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 4 deletions.
15 changes: 12 additions & 3 deletions src/core/labeling/qgslabelingengine.cpp
Expand Up @@ -282,9 +282,9 @@ void QgsLabelingEngine::registerLabels( QgsRenderContext &context )
for ( QgsAbstractLabelProvider *provider : std::as_const( mProviders ) )
{
std::unique_ptr< QgsExpressionContextScopePopper > layerScopePopper;
if ( QgsMapLayer *ml = provider->layer() )
if ( provider->layerExpressionContextScope() )
{
layerScopePopper = std::make_unique< QgsExpressionContextScopePopper >( context.expressionContext(), QgsExpressionContextUtils::layerScope( ml ) );
layerScopePopper = std::make_unique< QgsExpressionContextScopePopper >( context.expressionContext(), new QgsExpressionContextScope( *provider->layerExpressionContextScope() ) );
}
processProvider( provider, context, *mPal );
}
Expand Down Expand Up @@ -420,7 +420,7 @@ void QgsLabelingEngine::drawLabels( QgsRenderContext &context, const QString &la

// provider will require the correct layer scope for expression preparation - at this stage, the existing expression context
// only contains generic scopes
QgsExpressionContextScopePopper popper( context.expressionContext(), QgsExpressionContextUtils::layerScope( provider->layer() ) );
QgsExpressionContextScopePopper popper( context.expressionContext(), provider->layerExpressionContextScope() ? new QgsExpressionContextScope( *provider->layerExpressionContextScope() ) : new QgsExpressionContextScope() );
provider->startRender( context );
}

Expand Down Expand Up @@ -623,6 +623,10 @@ QgsAbstractLabelProvider::QgsAbstractLabelProvider( QgsMapLayer *layer, const QS
, mPriority( 0.5 )
, mUpsidedownLabels( QgsPalLayerSettings::Upright )
{
if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
{
mLayerExpressionContextScope.reset( vl->createExpressionContextScope() );
}
}

void QgsAbstractLabelProvider::drawUnplacedLabel( QgsRenderContext &, pal::LabelPosition * ) const
Expand Down Expand Up @@ -653,6 +657,11 @@ void QgsAbstractLabelProvider::stopRender( QgsRenderContext &context )
}
}

QgsExpressionContextScope *QgsAbstractLabelProvider::layerExpressionContextScope() const
{
return mLayerExpressionContextScope.get();
}

//
// QgsLabelingUtils
//
Expand Down
17 changes: 16 additions & 1 deletion src/core/labeling/qgslabelingengine.h
Expand Up @@ -127,7 +127,11 @@ class CORE_EXPORT QgsAbstractLabelProvider
//! Returns ID of associated layer, or empty string if no layer is associated with the provider.
QString layerId() const { return mLayerId; }

//! Returns the associated layer, or NULLPTR if no layer is associated with the provider.
/**
* Returns the associated layer, or NULLPTR if no layer is associated with the provider.
*
* \warning Accessing the layer is not thread safe, and this should never be called while the labeling engine is running from a background thread!
*/
QgsMapLayer *layer() const { return mLayer.data(); }

/**
Expand All @@ -152,6 +156,13 @@ class CORE_EXPORT QgsAbstractLabelProvider
//! How to handle labels that would be upside down
QgsPalLayerSettings::UpsideDownLabels upsidedownLabels() const { return mUpsidedownLabels; }

/**
* Returns the expression context scope created from the layer associated with this provider.
*
* \since QGIS 3.22
*/
QgsExpressionContextScope *layerExpressionContextScope() const;

protected:
//! Associated labeling engine
const QgsLabelingEngine *mEngine = nullptr;
Expand All @@ -174,6 +185,10 @@ class CORE_EXPORT QgsAbstractLabelProvider
QgsLabelObstacleSettings::ObstacleType mObstacleType = QgsLabelObstacleSettings::PolygonBoundary;
//! How to handle labels that would be upside down
QgsPalLayerSettings::UpsideDownLabels mUpsidedownLabels;

private:

std::unique_ptr< QgsExpressionContextScope > mLayerExpressionContextScope;
};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAbstractLabelProvider::Flags )
Expand Down

0 comments on commit 731810c

Please sign in to comment.