Skip to content

Commit

Permalink
Do not deadlock when calling when calling GetLayerVisibility
Browse files Browse the repository at this point in the history
... from multiple threads.

This is a partial solution (for most use cases, I believe).

Fix #53956
  • Loading branch information
elpaso committed Feb 1, 2024
1 parent c546ad0 commit 71b0bd9
Showing 1 changed file with 33 additions and 4 deletions.
37 changes: 33 additions & 4 deletions src/core/expression/qgsexpressioncontextutils.cpp
Expand Up @@ -994,10 +994,39 @@ QVariant QgsExpressionContextUtils::GetLayerVisibility::func( const QVariantList
}

bool isVisible = false;
Q_NOWARN_DEPRECATED_PUSH
QgsMapLayer *layer = QgsExpressionUtils::getMapLayer( values.at( 0 ), context, parent );
Q_NOWARN_DEPRECATED_POP
if ( layer && mLayers.contains( layer ) )

// getMapLayer() will happily deadlock if multiple expression are evaluated at
// the same time from different threads
// see: https://github.com/qgis/QGIS/issues/53956
// Searching by layer name/id in mLayer is safe and fast, let's do it first

QgsMapLayer *layer = nullptr;

if ( values.at( 0 ).type() == QVariant::String )
{
const QString layerIdOrName { values.at( 0 ).toString() };

for ( const auto &layerPtr : std::as_const( mLayers ) )
{
if ( layerPtr->id() == layerIdOrName || layerPtr->name() == layerIdOrName )
{
layer = layerPtr;
break;
}
}
}
else
{
Q_NOWARN_DEPRECATED_PUSH
layer = QgsExpressionUtils::getMapLayer( values.at( 0 ), context, parent );
Q_NOWARN_DEPRECATED_POP
if ( ! mLayers.contains( layer ) )
{
layer = nullptr;
}
}

if ( layer )
{
isVisible = true;
if ( mScaleBasedVisibilityDetails.contains( layer ) && !qgsDoubleNear( mScale, 0.0 ) )
Expand Down

0 comments on commit 71b0bd9

Please sign in to comment.