Skip to content

Commit

Permalink
QgisApp::closeProject(): cancel canvas jobs before closing the projec…
Browse files Browse the repository at this point in the history
…t, to avoid rendering jobs to access deleted objects (fixes #44144)
  • Loading branch information
rouault authored and nyalldawson committed Sep 24, 2021
1 parent 4859506 commit 0e45d51
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 9 deletions.
1 change: 1 addition & 0 deletions python/gui/auto_generated/qgsmapcanvas.sip.in
Expand Up @@ -149,6 +149,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 @@ -14000,6 +14000,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
27 changes: 18 additions & 9 deletions src/gui/qgsmapcanvas.cpp
Expand Up @@ -254,12 +254,29 @@ 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;
}


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 @@ -271,17 +288,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;
}


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 @@ -200,6 +200,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

1 comment on commit 0e45d51

@roya0045
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are crash report on closing qgis that may have been a side effect of this (see #46754 & #46388)

Please sign in to comment.