Skip to content

Commit

Permalink
Ensure GDAL deinitialization runs after last possible use
Browse files Browse the repository at this point in the history
Closes #14176
  • Loading branch information
Sandro Santilli committed Feb 2, 2016
1 parent 9fb7819 commit 0512538
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 13 deletions.
4 changes: 4 additions & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -876,6 +876,10 @@ void QgsApplication::exitQgis()

//delete all registered functions from expression engine (see above comment)
QgsExpression::cleanRegisteredFunctions();

// tear-down GDAL/OGR
OGRCleanupAll();
GDALDestroyDriverManager();
}

QString QgsApplication::showSettings()
Expand Down
3 changes: 2 additions & 1 deletion src/providers/gdal/qgsgdalprovider.cpp
Expand Up @@ -3021,5 +3021,6 @@ QGISEXTERN QList<QPair<QString, QString> > *pyramidResamplingMethods()

QGISEXTERN void cleanupProvider()
{
GDALDestroyDriverManager();
// nothing to do here, QgsApplication takes care of
// calling GDALDestroyDriverManager()
}
15 changes: 11 additions & 4 deletions src/providers/ogr/qgsogrconnpool.cpp
Expand Up @@ -15,12 +15,20 @@

#include "qgsogrconnpool.h"

QgsOgrConnPool QgsOgrConnPool::sInstance;
bool QgsOgrConnPool::sInstanceDestroyed = false;
QgsOgrConnPool* QgsOgrConnPool::mInstance = nullptr;

// static public
QgsOgrConnPool* QgsOgrConnPool::instance()
{
return sInstanceDestroyed ? nullptr : &sInstance;
if ( ! mInstance ) mInstance = new QgsOgrConnPool();
return mInstance;
}

// static public
void QgsOgrConnPool::cleanupInstance()
{
delete mInstance;
mInstance = nullptr;
}

QgsOgrConnPool::QgsOgrConnPool() : QgsConnectionPool<QgsOgrConn*, QgsOgrConnPoolGroup>()
Expand All @@ -31,5 +39,4 @@ QgsOgrConnPool::QgsOgrConnPool() : QgsConnectionPool<QgsOgrConn*, QgsOgrConnPool
QgsOgrConnPool::~QgsOgrConnPool()
{
QgsDebugCall;
sInstanceDestroyed = true;
}
27 changes: 20 additions & 7 deletions src/providers/ogr/qgsogrconnpool.h
Expand Up @@ -86,8 +86,25 @@ class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsOgr
class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn*, QgsOgrConnPoolGroup>
{
public:

// NOTE: first call to this function initializes the
// singleton.
// WARNING: concurrent call from multiple threads may result
// in multiple instances being created, and memory
// leaking at exit.
//
static QgsOgrConnPool* instance();

// Singleton cleanup
//
// Make sure nobody is using the instance before calling
// this function.
//
// WARNING: concurrent call from multiple threads may result
// in double-free of the instance.
//
static void cleanupInstance();

void ref( const QString& connInfo )
{
mMutex.lock();
Expand Down Expand Up @@ -118,14 +135,12 @@ class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn*, QgsOgrConnPoolGroup

static void refS( const QString &connInfo )
{
if ( instance() )
instance()->ref( connInfo );
instance()->ref( connInfo );
}

static void unrefS( const QString &connInfo )
{
if ( instance() )
instance()->unref( connInfo );
instance()->unref( connInfo );
}

protected:
Expand All @@ -134,9 +149,7 @@ class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn*, QgsOgrConnPoolGroup
private:
QgsOgrConnPool();
~QgsOgrConnPool();

static QgsOgrConnPool sInstance;
static bool sInstanceDestroyed;
static QgsOgrConnPool *mInstance;
};


Expand Down
4 changes: 3 additions & 1 deletion src/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -2857,5 +2857,7 @@ QGISEXTERN QgsVectorLayerImport::ImportError createEmptyLayer(

QGISEXTERN void cleanupProvider()
{
OGRCleanupAll();
QgsOgrConnPool::cleanupInstance();
// NOTE: QgsApplication takes care of
// calling OGRCleanupAll();
}

0 comments on commit 0512538

Please sign in to comment.