Skip to content

Commit

Permalink
SQL: Make QSqlDatabase::DriverDict creation thread-safe
Browse files Browse the repository at this point in the history
Make the QSqlDatabase::DriverDict thread-safe and make sure it's
properly cleaned up on destruction.

Fixes: QTBUG-112961
Change-Id: I1ff70e477579231754ef829fdede944d6042894d
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 048a68c)
  • Loading branch information
chehrlic committed Jul 8, 2023
1 parent e403c8d commit 8d2bdc9
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
31 changes: 16 additions & 15 deletions src/sql/kernel/qsqldatabase.cpp
Expand Up @@ -10,6 +10,7 @@
#include "qsqldriver.h"
#include "qsqldriverplugin.h"
#include "qsqlindex.h"
#include "QtCore/qapplicationstatic.h"
#include "private/qfactoryloader_p.h"
#include "private/qsqlnulldriver_p.h"
#include "qmutex.h"
Expand All @@ -26,8 +27,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,

const char *QSqlDatabase::defaultConnection = const_cast<char *>("qt_sql_default_connection");

typedef QHash<QString, QSqlDriverCreatorBase*> DriverDict;

class QConnectionDict: public QHash<QString, QSqlDatabase>
{
public:
Expand All @@ -46,6 +45,14 @@ class QConnectionDict: public QHash<QString, QSqlDatabase>
};
Q_GLOBAL_STATIC(QConnectionDict, dbDict)

namespace {
struct DriverDict : public QHash<QString, QSqlDriverCreatorBase*>
{
~DriverDict();
};
}
Q_APPLICATION_STATIC(DriverDict, qtDriverDict)

class QSqlDatabasePrivate
{
public:
Expand Down Expand Up @@ -121,23 +128,15 @@ void QSqlDatabasePrivate::cleanConnections()
dict->clear();
}

static bool qDriverDictInit = false;
static void cleanDriverDict()
DriverDict::~DriverDict()
{
qDeleteAll(QSqlDatabasePrivate::driverDict());
QSqlDatabasePrivate::driverDict().clear();
qDeleteAll(*this);
QSqlDatabasePrivate::cleanConnections();
qDriverDictInit = false;
}

DriverDict &QSqlDatabasePrivate::driverDict()
{
static DriverDict dict;
if (!qDriverDictInit) {
qDriverDictInit = true;
qAddPostRoutine(cleanDriverDict);
}
return dict;
return *qtDriverDict();
}

QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
Expand Down Expand Up @@ -511,7 +510,8 @@ QStringList QSqlDatabase::drivers()
list << it.value();
}

DriverDict dict = QSqlDatabasePrivate::driverDict();
QReadLocker locker(&dbDict()->lock);
const DriverDict &dict = QSqlDatabasePrivate::driverDict();
for (DriverDict::const_iterator i = dict.constBegin(); i != dict.constEnd(); ++i) {
if (!list.contains(i.key()))
list << i.key();
Expand Down Expand Up @@ -649,7 +649,8 @@ void QSqlDatabasePrivate::init(const QString &type)
drvName = type;

if (!driver) {
DriverDict dict = QSqlDatabasePrivate::driverDict();
QReadLocker locker(&dbDict()->lock);
const DriverDict &dict = QSqlDatabasePrivate::driverDict();
for (DriverDict::const_iterator it = dict.constBegin();
it != dict.constEnd() && !driver; ++it) {
if (type == it.key()) {
Expand Down
4 changes: 4 additions & 0 deletions tests/auto/sql/kernel/qsql/tst_qsql.cpp
Expand Up @@ -135,6 +135,10 @@ void tst_QSql::open()

void tst_QSql::openInvalid()
{
int argc = 1;
char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
QCoreApplication app(argc, argv, false);

QSqlDatabase db;
QVERIFY(!db.open());

Expand Down

0 comments on commit 8d2bdc9

Please sign in to comment.