mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Make sure ellipsoid parameter and definition caches are cleared before app exit (related to #31762)
This should apply to both PROJ < 6 and >=6 builds. Fixes the following error reported by Valgrind ``` ==5848== Invalid read of size 4 ==5848== at 0xE5E4195: internal_pj_ctx_get_errno (in /home/even/proj/install-proj-master/lib/libproj.so.15.2.0) ==5848== by 0xE5E16AE: internal_pj_free (in /home/even/proj/install-proj-master/lib/libproj.so.15.2.0) ==5848== by 0xE5F4E78: internal_proj_destroy (in /home/even/proj/install-proj-master/lib/libproj.so.15.2.0) ==5848== by 0x7F961A7: QgsProjUtils::ProjPJDeleter::operator()(PJconsts*) (qgsprojutils.cpp:76) ==5848== by 0x7D2D44C: std::unique_ptr<PJconsts, QgsProjUtils::ProjPJDeleter>::~unique_ptr() (unique_ptr.h:239) ==5848== by 0x7D2C9BD: QgsCoordinateReferenceSystemPrivate::~QgsCoordinateReferenceSystemPrivate() (qgscoordinatereferencesystem_p.h:94) ==5848== by 0x7D2D6FA: QExplicitlySharedDataPointer<QgsCoordinateReferenceSystemPrivate>::~QExplicitlySharedDataPointer() (qshareddata.h:165) ==5848== by 0x7CDFA77: QgsCoordinateReferenceSystem::~QgsCoordinateReferenceSystem() (qgscoordinatereferencesystem.cpp:233) ==5848== by 0x55CC0AF: QgsEllipsoidUtils::EllipsoidParameters::~EllipsoidParameters() (qgsellipsoidutils.h:39) ==5848== by 0x7D8C40B: QHashNode<QString, QgsEllipsoidUtils::EllipsoidParameters>::~QHashNode() (qhash.h:149) ==5848== by 0x7D8C43F: QHash<QString, QgsEllipsoidUtils::EllipsoidParameters>::deleteNode2(QHashData::Node*) (qhash.h:536) ==5848== by 0x9BE3B78: QHashData::free_helper(void (*)(QHashData::Node*)) (in /opt/qt59/lib/libQt5Core.so.5.9.1) ==5848== by 0x7D8C466: QHash<QString, QgsEllipsoidUtils::EllipsoidParameters>::freeData(QHashData*) (qhash.h:576) ==5848== by 0x7D8CCED: QHash<QString, QgsEllipsoidUtils::EllipsoidParameters>::~QHash() (qhash.h:254) ==5848== by 0xA60E369: __cxa_finalize (cxa_finalize.c:56) ==5848== by 0x77BE742: ??? (in /home/even/qgis/QGIS/build/output/lib/libqgis_core.so.3.9.0) ==5848== by 0x4010DF6: _dl_fini (dl-fini.c:235) ==5848== by 0xA60DFF7: __run_exit_handlers (exit.c:82) ==5848== by 0xA60E044: exit (exit.c:104) ==5848== by 0xA5F4836: (below main) (libc-start.c:325) ==5848== Address 0x45db80e0 is 0 bytes inside a block of size 136 free'd ==5848== at 0x4C2F440: operator delete(void*) (vg_replace_malloc.c:586) ==5848== by 0xE5F5A3A: internal_proj_context_destroy (in /home/even/proj/install-proj-master/lib/libproj.so.15.2.0) ==5848== by 0x7F9617A: QgsProjContext::~QgsProjContext() (qgsprojutils.cpp:48) ==5848== by 0xA60E5FE: __call_tls_dtors (cxa_thread_atexit_impl.c:155) ==5848== by 0xA60DF26: __run_exit_handlers (exit.c:40) ==5848== by 0xA60E044: exit (exit.c:104) ==5848== by 0xA5F4836: (below main) (libc-start.c:325) ==5848== Block was alloc'd at ==5848== at 0x4C2E709: operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:387) ==5848== by 0xE5E445E: internal_pj_ctx_alloc (in /home/even/proj/install-proj-master/lib/libproj.so.15.2.0) ==5848== by 0x7F96151: QgsProjContext::QgsProjContext() (qgsprojutils.cpp:39) ==5848== by 0x7F970A9: __tls_init (qgsprojutils.cpp:31) ==5848== by 0x7F970F3: TLS wrapper function for QgsProjContext::sProjContext (in /home/even/qgis/QGIS/build/output/lib/libqgis_core.so.3.9.0) ==5848== by 0x7F96186: QgsProjContext::get() (qgsprojutils.cpp:57) ==5848== by 0x7D86B13: QgsEllipsoidUtils::definitions() (qgsellipsoidutils.cpp:351) ==5848== by 0x7D863FE: QgsEllipsoidUtils::ellipsoidParameters(QString const&)::{lambda()#1}::operator()() const (qgsellipsoidutils.cpp:173) ==5848== by 0x7D87EE1: void std::_Bind_simple<QgsEllipsoidUtils::ellipsoidParameters(QString const&)::{lambda()#1} ()>::_M_invoke<>(std::_Index_tuple<>) (functional:1531) ==5848== by 0x7D87BC5: std::_Bind_simple<QgsEllipsoidUtils::ellipsoidParameters(QString const&)::{lambda()#1} ()>::operator()() (functional:1520) ==5848== by 0x7D879A2: void std::__once_call_impl<std::_Bind_simple<QgsEllipsoidUtils::ellipsoidParameters(QString const&)::{lambda()#1} ()> >() (mutex:706) ==5848== by 0x10A6AA98: __pthread_once_slow (pthread_once.c:116) ==5848== by 0x7D863CE: __gthread_once(int*, void (*)()) (gthr-default.h:699) ==5848== by 0x7D8787F: void std::call_once<QgsEllipsoidUtils::ellipsoidParameters(QString const&)::{lambda()#1}>(std::once_flag&, QgsEllipsoidUtils::ellipsoidParameters(QString const&)::{lambda()#1}&&) (mutex:738) ==5848== by 0x7D86476: QgsEllipsoidUtils::ellipsoidParameters(QString const&) (qgsellipsoidutils.cpp:174) ==5848== by 0x7E8D572: QgsMapSettings::setEllipsoid(QString const&) (qgsmapsettings.cpp:322) ==5848== by 0x6A4E5F1: QgsMapCanvas::QgsMapCanvas(QWidget*) (qgsmapcanvas.cpp:143) ==5848== by 0x5110841: QgisApp::QgisApp(QSplashScreen*, bool, bool, QString const&, QString const&, QWidget*, QFlags<Qt::WindowType>) (qgisapp.cpp:803) ==5848== by 0x417DB9: main (main.cpp:1339) ==5848== ```
This commit is contained in:
parent
738ced6488
commit
fdcca14f65
@ -64,6 +64,7 @@ ellipsoid database.
|
||||
.. seealso:: :py:func:`definitions`
|
||||
%End
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -351,15 +351,20 @@ QgsApplication::~QgsApplication()
|
||||
delete mQgisTranslator;
|
||||
delete mQtTranslator;
|
||||
|
||||
// invalidate coordinate cache while the PROJ context held by the thread-locale
|
||||
// QgsProjContextStore object is still alive. Otherwise if this later object
|
||||
// is destroyed before the static variables of the cache, we might use freed memory.
|
||||
|
||||
// we do this here as well as in exitQgis() -- it's safe to call as often as we want,
|
||||
// and there's just a *chance* that someone hasn't properly called exitQgis prior to
|
||||
// this destructor...
|
||||
invalidateCaches();
|
||||
}
|
||||
|
||||
void QgsApplication::invalidateCaches()
|
||||
{
|
||||
// invalidate coordinate cache while the PROJ context held by the thread-locale
|
||||
// QgsProjContextStore object is still alive. Otherwise if this later object
|
||||
// is destroyed before the static variables of the cache, we might use freed memory.
|
||||
QgsCoordinateTransform::invalidateCache( true );
|
||||
QgsCoordinateReferenceSystem::invalidateCache( true );
|
||||
QgsEllipsoidUtils::invalidateCache( true );
|
||||
}
|
||||
|
||||
QgsApplication *QgsApplication::instance()
|
||||
@ -1267,11 +1272,7 @@ void QgsApplication::exitQgis()
|
||||
if ( QgsProviderRegistry::exists() )
|
||||
delete QgsProviderRegistry::instance();
|
||||
|
||||
// invalidate coordinate cache AND DISABLE THEM! while the PROJ context held by the thread-locale
|
||||
// QgsProjContextStore object is still alive. Otherwise if this later object
|
||||
// is destroyed before the static variables of the cache, we might use freed memory.
|
||||
QgsCoordinateTransform::invalidateCache( true );
|
||||
QgsCoordinateReferenceSystem::invalidateCache( true );
|
||||
invalidateCaches();
|
||||
|
||||
QgsStyle::cleanDefaultStyle();
|
||||
|
||||
|
@ -923,6 +923,8 @@ class CORE_EXPORT QgsApplication : public QApplication
|
||||
static QgsAuthManager *sAuthManager;
|
||||
|
||||
static ApplicationMembers *members();
|
||||
|
||||
static void invalidateCaches();
|
||||
};
|
||||
|
||||
// clazy:excludeall=qstring-allocations
|
||||
|
@ -31,6 +31,7 @@ QReadWriteLock QgsEllipsoidUtils::sEllipsoidCacheLock;
|
||||
QHash< QString, QgsEllipsoidUtils::EllipsoidParameters > QgsEllipsoidUtils::sEllipsoidCache;
|
||||
QReadWriteLock QgsEllipsoidUtils::sDefinitionCacheLock;
|
||||
QList< QgsEllipsoidUtils::EllipsoidDefinition > QgsEllipsoidUtils::sDefinitionCache;
|
||||
static bool sDisableCache = false;
|
||||
|
||||
// maps older QGIS ellipsoid acronyms to proj acronyms/names
|
||||
const QMap< QString, QString > sProj6EllipsoidAcronymMap
|
||||
@ -179,12 +180,15 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
|
||||
// check cache
|
||||
{
|
||||
QgsReadWriteLocker locker( sEllipsoidCacheLock, QgsReadWriteLocker::Read );
|
||||
QHash< QString, EllipsoidParameters >::const_iterator cacheIt = sEllipsoidCache.constFind( ellipsoid );
|
||||
if ( cacheIt != sEllipsoidCache.constEnd() )
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
// found a match in the cache
|
||||
QgsEllipsoidUtils::EllipsoidParameters params = cacheIt.value();
|
||||
return params;
|
||||
QHash< QString, EllipsoidParameters >::const_iterator cacheIt = sEllipsoidCache.constFind( ellipsoid );
|
||||
if ( cacheIt != sEllipsoidCache.constEnd() )
|
||||
{
|
||||
// found a match in the cache
|
||||
QgsEllipsoidUtils::EllipsoidParameters params = cacheIt.value();
|
||||
return params;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +217,10 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
|
||||
}
|
||||
|
||||
QgsReadWriteLocker locker( sEllipsoidCacheLock, QgsReadWriteLocker::Write );
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
@ -256,7 +263,10 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
|
||||
QgsDebugMsg( QStringLiteral( "setEllipsoid: no row in tbl_ellipsoid for acronym '%1'" ).arg( ellipsoid ) );
|
||||
params.valid = false;
|
||||
sEllipsoidCacheLock.lockForWrite();
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
}
|
||||
sEllipsoidCacheLock.unlock();
|
||||
return params;
|
||||
}
|
||||
@ -269,7 +279,10 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
|
||||
QgsDebugMsg( QStringLiteral( "setEllipsoid: wrong format of radius field: '%1'" ).arg( radius ) );
|
||||
params.valid = false;
|
||||
sEllipsoidCacheLock.lockForWrite();
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
}
|
||||
sEllipsoidCacheLock.unlock();
|
||||
return params;
|
||||
}
|
||||
@ -292,7 +305,10 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
|
||||
QgsDebugMsg( QStringLiteral( "setEllipsoid: wrong format of parameter2 field: '%1'" ).arg( parameter2 ) );
|
||||
params.valid = false;
|
||||
sEllipsoidCacheLock.lockForWrite();
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
}
|
||||
sEllipsoidCacheLock.unlock();
|
||||
return params;
|
||||
}
|
||||
@ -320,14 +336,20 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
|
||||
params.crs = destCRS;
|
||||
|
||||
sEllipsoidCacheLock.lockForWrite();
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
}
|
||||
sEllipsoidCacheLock.unlock();
|
||||
return params;
|
||||
#else
|
||||
params.valid = false;
|
||||
|
||||
QgsReadWriteLocker l( sEllipsoidCacheLock, QgsReadWriteLocker::Write );
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sEllipsoidCache.insert( ellipsoid, params );
|
||||
}
|
||||
|
||||
return params;
|
||||
#endif
|
||||
@ -388,7 +410,10 @@ QList<QgsEllipsoidUtils::EllipsoidDefinition> QgsEllipsoidUtils::definitions()
|
||||
}
|
||||
|
||||
defs << def;
|
||||
sEllipsoidCache.insert( def.acronym, def.parameters );
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sEllipsoidCache.insert( def.acronym, def.parameters );
|
||||
}
|
||||
}
|
||||
|
||||
codesIt++;
|
||||
@ -444,7 +469,10 @@ QList<QgsEllipsoidUtils::EllipsoidDefinition> QgsEllipsoidUtils::definitions()
|
||||
{
|
||||
return collator.compare( a.description, b.description ) < 0;
|
||||
} );
|
||||
sDefinitionCache = defs;
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
sDefinitionCache = defs;
|
||||
}
|
||||
|
||||
return defs;
|
||||
}
|
||||
@ -459,3 +487,17 @@ QStringList QgsEllipsoidUtils::acronyms()
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void QgsEllipsoidUtils::invalidateCache( bool disableCache )
|
||||
{
|
||||
QgsReadWriteLocker locker1( sEllipsoidCacheLock, QgsReadWriteLocker::Write );
|
||||
QgsReadWriteLocker locker2( sDefinitionCacheLock, QgsReadWriteLocker::Write );
|
||||
|
||||
if ( !sDisableCache )
|
||||
{
|
||||
if ( disableCache )
|
||||
sDisableCache = true;
|
||||
sEllipsoidCache.clear();
|
||||
sDefinitionCache.clear();
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,19 @@ class CORE_EXPORT QgsEllipsoidUtils
|
||||
*/
|
||||
static QStringList acronyms();
|
||||
|
||||
#ifndef SIP_RUN
|
||||
|
||||
/**
|
||||
* Clears the internal cache used.
|
||||
*
|
||||
* If \a disableCache is TRUE then the inbuilt cache will be completely disabled. This
|
||||
* argument is for internal use only.
|
||||
*
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
static void invalidateCache( bool disableCache = false );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
// ellipsoid cache
|
||||
|
Loading…
x
Reference in New Issue
Block a user