Skip to content

Commit 8d2bdc9

Browse files
committed
SQL: Make QSqlDatabase::DriverDict creation thread-safe
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)
1 parent e403c8d commit 8d2bdc9

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

src/sql/kernel/qsqldatabase.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "qsqldriver.h"
1111
#include "qsqldriverplugin.h"
1212
#include "qsqlindex.h"
13+
#include "QtCore/qapplicationstatic.h"
1314
#include "private/qfactoryloader_p.h"
1415
#include "private/qsqlnulldriver_p.h"
1516
#include "qmutex.h"
@@ -26,8 +27,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
2627

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

29-
typedef QHash<QString, QSqlDriverCreatorBase*> DriverDict;
30-
3130
class QConnectionDict: public QHash<QString, QSqlDatabase>
3231
{
3332
public:
@@ -46,6 +45,14 @@ class QConnectionDict: public QHash<QString, QSqlDatabase>
4645
};
4746
Q_GLOBAL_STATIC(QConnectionDict, dbDict)
4847

48+
namespace {
49+
struct DriverDict : public QHash<QString, QSqlDriverCreatorBase*>
50+
{
51+
~DriverDict();
52+
};
53+
}
54+
Q_APPLICATION_STATIC(DriverDict, qtDriverDict)
55+
4956
class QSqlDatabasePrivate
5057
{
5158
public:
@@ -121,23 +128,15 @@ void QSqlDatabasePrivate::cleanConnections()
121128
dict->clear();
122129
}
123130

124-
static bool qDriverDictInit = false;
125-
static void cleanDriverDict()
131+
DriverDict::~DriverDict()
126132
{
127-
qDeleteAll(QSqlDatabasePrivate::driverDict());
128-
QSqlDatabasePrivate::driverDict().clear();
133+
qDeleteAll(*this);
129134
QSqlDatabasePrivate::cleanConnections();
130-
qDriverDictInit = false;
131135
}
132136

133137
DriverDict &QSqlDatabasePrivate::driverDict()
134138
{
135-
static DriverDict dict;
136-
if (!qDriverDictInit) {
137-
qDriverDictInit = true;
138-
qAddPostRoutine(cleanDriverDict);
139-
}
140-
return dict;
139+
return *qtDriverDict();
141140
}
142141

143142
QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
@@ -511,7 +510,8 @@ QStringList QSqlDatabase::drivers()
511510
list << it.value();
512511
}
513512

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

651651
if (!driver) {
652-
DriverDict dict = QSqlDatabasePrivate::driverDict();
652+
QReadLocker locker(&dbDict()->lock);
653+
const DriverDict &dict = QSqlDatabasePrivate::driverDict();
653654
for (DriverDict::const_iterator it = dict.constBegin();
654655
it != dict.constEnd() && !driver; ++it) {
655656
if (type == it.key()) {

tests/auto/sql/kernel/qsql/tst_qsql.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ void tst_QSql::open()
135135

136136
void tst_QSql::openInvalid()
137137
{
138+
int argc = 1;
139+
char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
140+
QCoreApplication app(argc, argv, false);
141+
138142
QSqlDatabase db;
139143
QVERIFY(!db.open());
140144

0 commit comments

Comments
 (0)