Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
QgisApp::closeProject(): cancel canvas jobs before closing the projec…
…t, to avoid rendering jobs to access deleted objects (fixes #44144)
  • Loading branch information
rouault authored and nyalldawson committed Sep 24, 2021
1 parent ed708e6 commit b0e37d8
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 10 deletions.
1 change: 1 addition & 0 deletions python/gui/auto_generated/qgsmapcanvas.sip.in
Expand Up @@ -133,6 +133,7 @@ Make sure to remove any rendered images from cache (does nothing if cache is not
.. versionadded:: 2.4
%End


void waitWhileRendering();
%Docstring
Blocks until the rendering job has finished.
Expand Down
1 change: 1 addition & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -13387,6 +13387,7 @@ void QgisApp::closeProject()
// clear out any stuff from project
mMapCanvas->setLayers( QList<QgsMapLayer *>() );
mMapCanvas->clearCache();
mMapCanvas->cancelJobs();
mOverviewCanvas->setLayers( QList<QgsMapLayer *>() );

// Avoid unnecessary layer changed handling for each layer removed - instead,
Expand Down
29 changes: 19 additions & 10 deletions src/gui/qgsmapcanvas.cpp
Expand Up @@ -242,12 +242,30 @@ QgsMapCanvas::~QgsMapCanvas()
}
mLastNonZoomMapTool = nullptr;

cancelJobs();

// delete canvas items prior to deleting the canvas
// because they might try to update canvas when it's
// already being destructed, ends with segfault
qDeleteAll( mScene->items() );

mScene->deleteLater(); // crashes in python tests on windows

delete mCache;
delete mLabelingResults;
}


void QgsMapCanvas::cancelJobs()
{

// rendering job may still end up writing into canvas map item
// so kill it before deleting canvas items
if ( mJob )
{
whileBlocking( mJob )->cancel();
delete mJob;
mJob = nullptr;
}

QList< QgsMapRendererQImageJob * >::const_iterator previewJob = mPreviewJobs.constBegin();
Expand All @@ -259,18 +277,9 @@ QgsMapCanvas::~QgsMapCanvas()
delete *previewJob;
}
}

// delete canvas items prior to deleting the canvas
// because they might try to update canvas when it's
// already being destructed, ends with segfault
qDeleteAll( mScene->items() );

mScene->deleteLater(); // crashes in python tests on windows

delete mCache;
delete mLabelingResults;
}


void QgsMapCanvas::setMagnificationFactor( double factor, const QgsPointXY *center )
{
// do not go higher or lower than min max magnification ratio
Expand Down
6 changes: 6 additions & 0 deletions src/gui/qgsmapcanvas.h
Expand Up @@ -183,6 +183,12 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex
*/
void clearCache();

/**
* Cancel any rendering job, in a blocking way. Used for application closing.
* \note not available in Python bindings
*/
void cancelJobs() SIP_SKIP;

/**
* Blocks until the rendering job has finished.
*
Expand Down

0 comments on commit b0e37d8

Please sign in to comment.