Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

vs2017+Qt5.12.6 database cross-thread access fails



  • Problem Description:

    The original code uses Qt5.4 msvc to compile a 32-bit program, and the initialization of the database is placed in the thread. The access is in other threads. There is no problem.

    The same code is upgraded to Qt5.12.6 to compile 64 bits, and initialization can be successful. Access fails. Prompt drive not loaded,I have tried to let them run on the same thread is no problem, but cross-thread does not work

    code show as below:

    bool BTDatabaseCtl::initDB(const QString &dbName, const QString &password)
    {
        **// Initialize in thread**
        mMutex.lock();
    
        bool flag = false;
        if (mDriver == nullptr)
        {
            mDriver = new ZSQLiteCipherDriver();
        }
        else
        {
            mMutex.unlock();
    
            return true;
        }
    
        mDBName = dbName;
        mPassword = password;
        mConnectionName = BTAppHelper::creatUid();
        QSqlDatabase innerDB = QSqlDatabase::addDatabase(mDriver, mConnectionName);
    
        switch (openDB(innerDB, dbName, password))
        {
        case -2:
            LOG_ERROR() << "Open database failed." << dbName;
            break;
    
        case -1:
            LOG_ERROR() << "Create database failed." << dbName;
            break;
    
        case 0:
            LOG_ERROR() << "Incorrect password/not database file." << dbName;
            break;
    
        case 1:
            LOG_DEBUG() << "Create database succeeded." << dbName;
            flag = true;
            break;
    
        case 2:
            LOG_DEBUG() << "Open database succeeded." << dbName;
            flag = true;
            break;
        }
    
        mMutex.unlock();
    
        return flag;
    }
    
    int BTDatabaseCtl::openDB(QSqlDatabase &db, const QString &dbName, const QString &password)
    {
        QFile file(dbName);
        bool isDbFileExists = file.exists() && (file.size() > 0);
        db.setDatabaseName(dbName);
        db.setPassword(password);
    
        if (!db.open())
        {
            return isDbFileExists ? -2 : -1;
        }
    
        if (isDbFileExists && !isDbDecrypted(db))
        {
            db.close();
            return 0;
        }
    
        return isDbFileExists ? 2 : 1;
    }
    
    QSqlDatabase BTDatabaseCtl::getEncryptedDB()
    {
        mMutex.lock();
    
        **// Database connection name exists**
        if (QSqlDatabase::contains(mConnectionName))
        {
            **// But the fetch fails here. db.isValid() returns false**
            QSqlDatabase db = QSqlDatabase::database(mConnectionName);
            if (db.isOpen())
            {
                mMutex.unlock();
    
                return db;
            }
    
            db.setDatabaseName(mDBName);
            db.setPassword(mPassword);
    
            if (!db.open())
            {
                LOG_ERROR() << "Open database failed:" << mDBName;
            }
    
            mMutex.unlock();
    
            return db;
        }
    
        QSqlDatabase innerDB = QSqlDatabase::addDatabase(mDriver, mConnectionName);
        innerDB.setDatabaseName(mDBName);
        innerDB.setPassword(mPassword);
    
        if (!innerDB.open())
        {
            LOG_ERROR() << "Open database failed:" << mDBName;
        }
    
        mMutex.unlock();
    
        return innerDB;
    }
    

  • Lifetime Qt Champion

    @simon_01 said in vs2017+Qt5.12.6 database cross-thread access fails:

    The access is in other threads.

    You are not allowed to pass a QSqlDatabase around into other threads. You have to open the database in the thread where you use it. This was not checked in previous Qt version but is in 5.12 and higher.


  • Lifetime Qt Champion

    @simon_01 said in vs2017+Qt5.12.6 database cross-thread access fails:

    The access is in other threads.

    You are not allowed to pass a QSqlDatabase around into other threads. You have to open the database in the thread where you use it. This was not checked in previous Qt version but is in 5.12 and higher.



  • @Christian-Ehrlicher said in vs2017+Qt5.12.6 database cross-thread access fails:

    @simon_01 said in vs2017+Qt5.12.6 database cross-thread access fails:

    The access is in other threads.

    You are not allowed to pass a QSqlDatabase around into other threads. You have to open the database in the thread where you use it. This was not checked in previous Qt version but is in 5.12 and higher.

    Thanks a lot,it's works

    QSqlDatabase BTDatabaseCtl::getEncryptedDB()
    {
        mMutex.lock();
    
    	if (QSqlDatabase::contains(mConnectionName))
    	{
    		QSqlDatabase db = QSqlDatabase::database(mConnectionName);
    		if (db.isOpen())
    		{
    			mMutex.unlock();
    
    			return db;
    		}
    	}
    
        QSqlDatabase innerDB = QSqlDatabase::addDatabase(mDriver, mConnectionName);
        innerDB.setDatabaseName(mDBName);
        innerDB.setPassword(mPassword);
    
        if (!innerDB.open())
        {
            LOG_ERROR() << "Open database failed:" << mDBName;
        }
    
        mMutex.unlock();
    
        return innerDB;
    }
    

Log in to reply