Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt MySQL adapter refuses to connect randomly: Unable to allocate a MYSQL

Tags:

c++

mysql

qt

qt5

I'm using QMYSQL to connect to a local database. The application runs over several threads. Each thread connects to database using an independent connection. Sometimes Qt throws following error when I try to connect to database. What's the problem?

QMYSQL: Unable to allocate a MYSQL object

Update

Added the code used to connect. This object is moved to a thread, the connection is named. critical is a signal emitted to main window to terminate application execution after a critical error (showing a message). log is a signal that is emitted to log incidences into database.

void ClientWorker::connect() {
    m_database = QSqlDatabase::addDatabase("QMYSQL","wsc");
    m_database.setHostName(m_host);
    m_database.setDatabaseName(m_databaseName);
    m_database.setPort(m_port);
    m_database.setUserName(m_db_username);
    m_database.setPassword(m_db_password);
    if(!m_database.open()) {
        QString error = "Unable to connect to database. Reason:\n";
        error+= m_database.lastError().text();
        log("Unable to connect to database! ", error, "ERROR" );
        emit critical(tr("Database Error!"),error);
    } else {
        log("Connected to datbase successfully.", "", "NOTICE" );
}

Update 2

I just realized that every time a connection is made out of main thread, (with no active connections in main tread) the driver fails to load. I just added a small dummy connection code in main() that connects and disconnects immediately (before any thread connects). Adding that code, everything works fine. I'm not sure why threads can't connect before a connection in main thread, but I think it looks like a bug. Hope this helps someone, Took 3 days of mine :/

like image 566
sorush-r Avatar asked Jul 13 '16 06:07

sorush-r


1 Answers

You might not care after your last update, but I have a theory based on it: this indicates mysql_library_init() has to be called from main() for multithreaded applications.

If you look in the Qt plugin source, that method is wrapped in qLibraryInit(), which is called from the QMYSQLDriver : QSqlDriver constructors, which in turn I believe get created indirectly by addDatabase() in your usage context.

The MySQL docs note that the mysql_library_init() can be done protected by a mutex, which would entail the QtSql code protecting all QSqlDriver construction, which I don't think it does. So I'm not sure if this would be considered a Qt code bug or a gap in documentation.

This all fits the behavior you've described, but I'm still doubtful of myself - if this is correct it surprises me that more people haven't run into this and it's not more evident on SO and other fora. I guess it's a little unusual to do your first DB activity on a spawned thread vs. at least some initial work in the main thread?

like image 159
eclarkso Avatar answered Oct 04 '22 23:10

eclarkso