PDA

View Full Version : MySql: my_thread_global_end(): 1 threads didn't exit



mentalmushroom
16th September 2014, 15:13
When QSqlDatabase::removeDatabase() is called from a different thread than QSqlDatabase::addDatabase() was called from, I get the following error message:

Error in my_thread_global_end(): 1 threads didn't exit

It is easy to reproduce with the following code sample even without MySql database. But it seems to happen on Ubuntu and NOT on Windows.



#include <QtCore>
#include <QtSql>

class Client: public QObject
{
Q_OBJECT

public:
Client();
~Client();

public slots:
void start();

signals:
void done();
}; // Client

Client::Client()
{
QSqlDatabase::addDatabase("QMYSQL", "my_connection");
}

Client::~Client()
{
}

void Client::start()
{
// we could do some work here, but for the test simply remove the connection
QSqlDatabase::removeDatabase("my_connection");
emit done();
}


int main(int argc, char* argv[])
{
QCoreApplication app(argc, argv);

QThread t;
Client client;
client.moveToThread(&t);
QObject::connect(&t, SIGNAL(started()), &client, SLOT(start()));
QObject::connect(&client, SIGNAL(done()), &t, SLOT(quit()));
QObject::connect(&t, SIGNAL(finished()), &app, SLOT(quit()));
t.start();

return app.exec();
}

#include "main.moc"



What am I doing wrong?

wysota
16th September 2014, 17:38
What am I doing wrong?
You are removing the database from a wrong thread. QSqlDatabase (and friends) objects are not to be used from within different threads.

Threads and the sql module

mentalmushroom
19th September 2014, 08:17
Ok, good to know. But I noticed the error happens when I add and remove the connection from the same thread either, but less regular.

The issue can be noticed with the following code sample:


#include <QtCore>
#include <QtSql>

class Client: public QRunnable
{
public:
virtual void run();
};

void Client::run()
{
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", QString::number((unsigned long long)QThread::currentThreadId()));

db.setHostName("localhost");
db.setDatabaseName("test");
db.setUserName("me");
db.setPassword("mypass");

db.open();

//QSqlQuery q(strQuery);
}

QSqlDatabase::removeDatabase(QString::number((unsi gned long long)QThread::currentThreadId()));

}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QThreadPool pool;
pool.setMaxThreadCount(100);

for (int i = 0; i < 100; ++i)
{
Client *client = new Client;
bool started = pool.tryStart(client);
Q_ASSERT(started);
}

pool.waitForDone();

//return a.exec();
return 0;
}


Here goes the output of two successive runs:


mushroom@ubuntu:~/projects/mysqltest/mysqlthread/debug$ ./mysqlthread
Error in my_thread_global_end(): 48 threads didn't exit

mushroom@ubuntu:~/projects/mysqltest/mysqlthread/debug$ ./mysqlthread
Error in my_thread_global_end(): 33 threads didn't exit
Error in my_thread_global_end(): 85 threads didn't exit

wysota
19th September 2014, 10:15
Close the database first before removing it.

mentalmushroom
19th September 2014, 13:57
I've updated the code, so it is closed:


#include <QtCore>
#include <QtSql>

class Client: public QRunnable
{
public:
virtual void run();
};

void Client::run()
{
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", QString::number((unsigned long long)QThread::currentThreadId()));

db.setHostName("localhost");
db.setDatabaseName("test");
db.setUserName("me");
db.setPassword("mypass");

db.open();

db.close(); // ! close the database before removing it !
}

QSqlDatabase::removeDatabase(QString::number((unsi gned long long)QThread::currentThreadId()));

}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QThreadPool pool;
pool.setMaxThreadCount(100);

for (int i = 0; i < 100; ++i)
{
Client *client = new Client;
bool started = pool.tryStart(client);
Q_ASSERT(started);
}

pool.waitForDone();

return 0;
}


The error still persists:


mushroom@ubuntu:~/projects/mysqltest/mysqlthread/debug$ ./mysqlthread
Error in my_thread_global_end(): 51 threads didn't exit
Error in my_thread_global_end(): 65 threads didn't exit

gfernandes
21st October 2014, 13:50
Hi,

I have the same issue. Did you resolve your issue? If yes, could you please share your solution?

Thank you

mentalmushroom
22nd October 2014, 10:35
No, I didn't, but so far I can't see any obvious issues, except that warning message. However, I've reported it to the bug tracker (https://bugreports.qt-project.org/browse/QTBUG-41483?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab). Vote for it, if it worries you.

danadam
5th May 2015, 16:36
From what I found out, there may be two causes for that:

QSqlDatabase::addDatabase() and QSqlDatabase::removeDatabase() are not entirely thread-safe when using MySQL driver (maybe also when using other drivers, I didn't check them)
MySQL driver doesn't clean up properly after itself when call to QSqlDatabase::open() fails.

See my response to your bug for more details.