Bug report #21376

QGIS crashes when working with QgsLayerTreeLayers in a processing script

Added by Jochen Schwarze about 5 years ago. Updated about 5 years ago.

Status:Closed
Priority:High
Assignee:-
Category:Processing/QGIS
Affected QGIS version:3.6.0 Regression?:No
Operating System: Easy fix?:No
Pull Request or Patch supplied:No Resolution:invalid
Crashes QGIS or corrupts data:Yes Copied to github as #:29193

Description

User Feedback

Trying to reorder layers from a processing script causes QGIS to crash. The following code works from the python console, but causes QGIS to crash when used within a processing script:

layer_order = [u'formelsammlung',
            'kabeld',
            'KabelD nicht zuordbar',
            'Erschlossene Flaechen',
            'ax_flurstueck',
            'Flurstuecke erschlossen (KabelD)',
            'Flurstuecke n. eind. erschl.',
            'ax_adressen',
            'Adressen erschlossen (KabelD)',
            'Adressen auf n. eind. erschl. Flst.']

        root = QgsProject.instance().layerTreeRoot()      

        for lyr_name in layer_order:
            lyrs = QgsProject.instance().mapLayersByName(lyr_name)
            if len(lyrs) > 0:
                lyr = lyrs[0]
                my_lyr = root.findLayer(lyr.id())
                my_clone = my_lyr.clone()
                root.insertChildNode(0, my_clone)
                root.removeChildNode(my_lyr)

This is the script that causes the script:

from PyQt5.QtCore import QCoreApplication
from qgis.core import QgsProject, QgsProcessingAlgorithm, QgsProcessingParameterFile, QgsProcessingParameterVectorLayer, QgsProcessing
from qgis.utils import iface

import processing

class BBBBLayerStylerProcessingAlgorithm(QgsProcessingAlgorithm):
    STYLE_FOLDER = 'STYLE_FOLDER'
    INPUT_ADR = 'INPUT_ADR'
    INPUT_FLST = 'INPUT_FLST'

    def tr(self, string):
        return QCoreApplication.translate('Processing', string)

    def createInstance(self):
        return BBBBLayerStylerProcessingAlgorithm()

    def name(self):
        return 'bbbblayerstylercrashtest'

    def displayName(self):
        return self.tr('BBBB Layer Styler /Crashtest')

    def group(self):
        return self.tr('giswg')

    def groupId(self):
        return 'giswg'

    def shortHelpString(self):
        return self.tr("Apply styles and order layers from BBBB analysis")

    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterFile(
                self.STYLE_FOLDER,
                self.tr('Style folder'),
                QgsProcessingParameterFile.Folder,
                '',
                'H:\\BBBB\\_styles_test_etc'
            )
        )

        self.addParameter(
            QgsProcessingParameterVectorLayer(
                self.INPUT_ADR,
                self.tr('Input address layer'),
                [QgsProcessing.TypeVectorPoint]
            )
        )

        self.addParameter(
            QgsProcessingParameterVectorLayer(
                self.INPUT_FLST,
                self.tr('Input parcels layer'),
                [QgsProcessing.TypeVectorPolygon]
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        folder = self.parameterAsFile(
            parameters,
            self.STYLE_FOLDER,
            context
        )

        input_adr_lyr = self.parameterAsVectorLayer(
            parameters,
            self.INPUT_ADR,
            context
        )

        input_flst_lyr = self.parameterAsVectorLayer(
            parameters,
            self.INPUT_FLST,
            context
        )

        layer_order = [u'formelsammlung',
            'kabeld',
            'KabelD nicht zuordbar',
            'Erschlossene Flaechen',
            'ax_flurstueck',
            'Flurstuecke erschlossen (KabelD)',
            'Flurstuecke n. eind. erschl.',
            'ax_adressen',
            'Adressen erschlossen (KabelD)',
            'Adressen auf n. eind. erschl. Flst.']

        root = QgsProject.instance().layerTreeRoot()

        feedback.setProgressText('\norder layers ...')        

        for lyr_name in layer_order:
            lyrs = QgsProject.instance().mapLayersByName(lyr_name)
            if len(lyrs) > 0:
                lyr = lyrs[0]
                my_lyr = root.findLayer(lyr.id())
                my_clone = my_lyr.clone()
                root.insertChildNode(0, my_clone)
                root.removeChildNode(my_lyr)

        feedback.setProgressText('\n------------ ALL DONE --------------')

        return {}

Report Details

Crash ID: 7972d0aa46f3682d49822a6e9e6d72944a22cffd

Stack Trace

QgsTransformEffect::readProperties :
QgsLayerTreeNode::children :
QgsLayerCapabilitiesModel::trUtf8 :
QMetaCallEvent::placeMetaCall :
QObject::event :
QApplicationPrivate::notify_helper :
QApplication::notify :
QgsApplication::notify :
QCoreApplication::notifyInternal2 :
QCoreApplicationPrivate::sendPostedEvents :
qt_plugin_query_metadata :
QEventDispatcherWin32::processEvents :
CallWindowProcW :
DispatchMessageW :
QEventDispatcherWin32::processEvents :
qt_plugin_query_metadata :
QEventLoop::exec :
QDialog::exec :
PyMethodDef_RawFastCallKeywords :
PyMethodDef_RawFastCallKeywords :
PyEval_EvalFrameDefault :
PyFunction_FastCallDict :
PyMethodDef_RawFastCallDict :
PyObject_Call :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
QMetaObject::activate :
QAbstractItemView::doubleClicked :
QTreeView::mouseDoubleClickEvent :
QWidget::event :
QFrame::event :
QAbstractItemView::viewportEvent :
QCoreApplicationPrivate::sendThroughObjectEventFilters :
QApplicationPrivate::notify_helper :
QApplication::notify :
QgsApplication::notify :
QCoreApplication::notifyInternal2 :
QApplicationPrivate::sendMouseEvent :
QSizePolicy::QSizePolicy :
QSizePolicy::QSizePolicy :
QApplicationPrivate::notify_helper :
QApplication::notify :
QgsApplication::notify :
QCoreApplication::notifyInternal2 :
QGuiApplicationPrivate::processMouseEvent :
QWindowSystemInterface::sendWindowSystemEvents :
QEventDispatcherWin32::processEvents :
CallWindowProcW :
DispatchMessageW :
QEventDispatcherWin32::processEvents :
qt_plugin_query_metadata :
QEventLoop::exec :
QCoreApplication::exec :
main :
BaseThreadInitThunk :
RtlUserThreadStart :

QGIS Info
QGIS Version: 3.6.0-Noosa
QGIS code revision: 58734527ab
Compiled against Qt: 5.11.2
Running against Qt: 5.11.2
Compiled against GDAL: 2.4.0
Running against GDAL: 2.4.0

System Info
CPU Type: x86_64
Kernel Type: winnt
Kernel Version: 10.0.17134

History

#1 Updated by Nyall Dawson about 5 years ago

  • Resolution set to invalid
  • Status changed from Open to Closed

You need to indicate that your algorithm CANNOT be run in a background thread by adding:

def flags(self):
return super().flags() | QgsProcessingAlgorithm.FlagNoThreading

Also available in: Atom PDF