Crash in qsqlite module
-
Hello,
maybe somebody can help me or give me some hints what i can do to avoid such crashes ?What im doing:
- Each Image is stored via an unique hash and the image data in my sqlite database
- When trying to display the image (via GraphicItem) the data is loaded from the sqlite database with the image hash
- This all happens Multithreaded. So for each Loading attempt an own sql connection is made because QSqlDatabase can only be accessed in the thread being created
- The crash is not reproducible on my machine
I am using Qt Version 5.12.9.
-
Hi,
How are you setting up the database connection ?
Might be unrelated but how are you getting the image back to your QGraphicsItem ?
-
bool DbFile::requestDb(QSqlDatabase &db) const { // mkh20130206: QSqlDatabase can only be accessed in the thread being created int tid = _threadId(); QString connectionName = QString("%1-%2").arg(mFileName).arg(tid); bool retVal = false; if (QSqlDatabase::contains(connectionName)) { db = QSqlDatabase::database(connectionName); retVal = db.isValid() && db.isOpen(); } else { db = QSqlDatabase::addDatabase("QSQLITE", connectionName); if (db.isValid()) { db.setDatabaseName(mFileName); retVal = db.open(); if (retVal) { // store created db connection for later destroy QMutexLocker _accessLock(&mConnectionsLock); mConnections << connectionName; } } } return retVal; }
That's the code for the creation of the database connection.
The Image is sent back as QByteArray. After that is is used for creating QPixmap or QImage (depends on the use case):
data = q.value(0).toByteArray();
-
Is that requestDb method called in a method that runs in the thread using the connection ?
-
Yes. The requestDb Method ensures that a connection is used which is created only for that Thread.
Therefore a unique thread id is generated and used as connection name. Look at the following line.int tid = _threadId(); QString connectionName = QString("%1-%2").arg(mFileName).arg(tid);
static QHash<QThread*, int> _threadIds; static int _threadCounter; static QMutex _threadIdLock(QMutex::Recursive); int _threadId() { QMutexLocker _accessLock(&_threadIdLock); QThread *curThread = QThread::currentThread(); if (!_threadIds.contains(curThread)) { if (qApp->thread() == curThread) { _threadIds[curThread] = 0; } else { _threadIds[curThread] = ++_threadCounter; } } return _threadIds[curThread]; }
-
SQlite is not threadsafe by default: https://sqlite.org/threadsafe.html
Also Qt does not compile the sqlite plugin with SQLITE_THREADSAFE -
@euchkatzl Compile the qt sql plugin with the define I mentioned and activate it as described in the link I gave you.