Skip to content
This repository was archived by the owner on Mar 4, 2023. It is now read-only.

Commit 958ce63

Browse files
committed
safer database cleanups
1 parent f9e0809 commit 958ce63

File tree

6 files changed

+40
-16
lines changed

6 files changed

+40
-16
lines changed

src/datasync/datasync.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
TARGET = QtDataSync
22

33
QT = core jsonserializer sql websockets scxml remoteobjects remoteobjects-private
4-
android: QT += androidextras #needed to deploy the android keystore plugin
4+
#android: QT += androidextras #needed to deploy the android keystore plugin
55

66
HEADERS += \
77
qtdatasync_global.h \

src/datasync/defaults.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ QSqlDatabase *DatabaseRef::operator->() const
192192
const QString DefaultsPrivate::DatabaseName(QStringLiteral("__QtDataSync_database_%1_0x%2"));
193193
QMutex DefaultsPrivate::setupDefaultsMutex;
194194
QHash<QString, QSharedPointer<DefaultsPrivate>> DefaultsPrivate::setupDefaults;
195-
QThreadStorage<QHash<QString, quint64>> DefaultsPrivate::dbRefHash;
195+
thread_local DefaultsPrivate::DatabaseHolder DefaultsPrivate::dbRefHash;
196196

197197
void DefaultsPrivate::createDefaults(const QString &setupName, bool isPassive, const QDir &storageDir, const QUrl &roAddress, const QHash<Defaults::PropertyKey, QVariant> &properties, QJsonSerializer *serializer, ConflictResolver *resolver)
198198
{
@@ -287,7 +287,7 @@ QSqlDatabase DefaultsPrivate::acquireDatabase()
287287
{
288288
auto name = DefaultsPrivate::DatabaseName
289289
.arg(setupName, QString::number(reinterpret_cast<quint64>(QThread::currentThread()), 16));
290-
if((dbRefHash.localData()[setupName])++ == 0) {
290+
if((dbRefHash[setupName])++ == 0) {
291291
logDebug() << "Acquiring database for thread" << QThread::currentThread();
292292
auto database = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), name);
293293
database.setDatabaseName(storageDir.absoluteFilePath(QStringLiteral("store.db")));
@@ -331,12 +331,9 @@ QSqlDatabase DefaultsPrivate::acquireDatabase()
331331

332332
void DefaultsPrivate::releaseDatabase()
333333
{
334-
if(--(dbRefHash.localData()[setupName]) == 0) {
334+
if(--(dbRefHash[setupName]) == 0) {
335335
logDebug() << "Releasing database for thread" << QThread::currentThread();
336-
auto name = DefaultsPrivate::DatabaseName
337-
.arg(setupName, QString::number(reinterpret_cast<quint64>(QThread::currentThread()), 16));
338-
QSqlDatabase::database(name).close();
339-
QSqlDatabase::removeDatabase(name);
336+
releaseDatabaseImpl(setupName);
340337
}
341338
}
342339

@@ -385,6 +382,29 @@ void DefaultsPrivate::makePassive()
385382
}
386383
}
387384

385+
void DefaultsPrivate::releaseDatabaseImpl(const QString &name)
386+
{
387+
auto dbName = DefaultsPrivate::DatabaseName
388+
.arg(name, QString::number(reinterpret_cast<quint64>(QThread::currentThread()), 16));
389+
QSqlDatabase::database(dbName).close();
390+
QSqlDatabase::removeDatabase(dbName);
391+
}
392+
393+
394+
395+
DefaultsPrivate::DatabaseHolder::~DatabaseHolder()
396+
{
397+
for(auto it = constBegin(); it != constEnd(); it++) {
398+
if(*it <= 0)
399+
continue;
400+
qCCritical(qdssetup) << "Setup" << it.key()
401+
<< "still has" << *it
402+
<< "open database references in thread" << QThread::currentThread()
403+
<< "on destruction of that thread! Database will be force-closed";
404+
releaseDatabaseImpl(it.key());
405+
}
406+
}
407+
388408
// ------------- PRIVATE IMPLEMENTATION DatabaseRef -------------
389409

390410
DatabaseRefPrivate::DatabaseRefPrivate(QSharedPointer<DefaultsPrivate> defaultsPrivate, QObject *object) :

src/datasync/defaults_p.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,16 @@ private Q_SLOTS:
8080
void makePassive();
8181

8282
private:
83+
static void releaseDatabaseImpl(const QString &name);
84+
85+
struct DatabaseHolder : public QHash<QString, quint64>
86+
{
87+
~DatabaseHolder();
88+
};
89+
8390
static QMutex setupDefaultsMutex;
8491
static QHash<QString, QSharedPointer<DefaultsPrivate>> setupDefaults;
85-
static QThreadStorage<QHash<QString, quint64>> dbRefHash;
92+
static thread_local DatabaseHolder dbRefHash;
8693

8794
QString setupName;
8895
QDir storageDir;

src/datasync/exchangeengine.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -342,18 +342,15 @@ ExchangeEngine::ImportData::ImportData(QJsonObject data, QString password, bool
342342

343343
// ------------- Engine Thread -------------
344344

345+
thread_local QSharedPointer<EngineThread> EngineThread::_deleteBlocker;
346+
345347
EngineThread::EngineThread(QString setupName, ExchangeEngine *engine, QLockFile *lockFile) :
346348
_name{std::move(setupName)},
347349
_engine{engine},
348350
_lockFile{lockFile}
349351
{
350352
setTerminationEnabled(true);
351353
_engine.load()->moveToThread(this);
352-
353-
connect(this, &QThread::finished,
354-
this, [this](){
355-
_deleteBlocker.clear();
356-
}, Qt::QueuedConnection);
357354
}
358355

359356
EngineThread::~EngineThread()

src/datasync/exchangeengine_p.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class EngineThread : public QThread
145145
QAtomicInteger<quint16> _running = false;
146146

147147
//delete blocker
148-
QSharedPointer<EngineThread> _deleteBlocker;
148+
static thread_local QSharedPointer<EngineThread> _deleteBlocker;
149149
};
150150

151151
}

src/datasync/setup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ SetupPrivate::SetupPrivate() :
608608

609609
void SetupPrivate::deleteThread(EngineThread *thread)
610610
{
611-
thread->deleteLater();
611+
delete thread;
612612
}
613613

614614
// ------------- Exceptions -------------

0 commit comments

Comments
 (0)