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

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 :/

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?

There is a bug related with QSqlDatabase::isOpen() in Qt.
http://bugreports.qt-project.org/browse/QTBUG-223
QSqlQuery::lastError() should give you an error if your query via QSqlQuery::exec() has failed. Also QSqlDatabase::isOpen() should report the state of your connection, QSqlDatabase::lastError() is also available

Related

C++/QT Safely terminate a blocking thread

I am creating an application, that communicates with a server using an API's functions, from an existing code base written in C++/Qt 5.6 and Boost. The code is written in a way such that, any communication with the server is done by the API's functions that runs in a worker object. The worker object runs in a QThread(), and is moved using moveToThread.
My problem is that, I need to be able to stop the thread immediately and disconnect in the situation where the network connection drops. However, the thread blocks when it sends data to the server. If I try to stop the thread through quit() or wait(), the request still goes through to the server which is undesirable. The API doesn't offer any method to cancel any ongoing requests either.
My current solution is terminating the thread, and destroying the worker object it owns when the network connection drops. I then create a new QThread and new worker object when connecting to the server.
I know that terminate() or any kind of immediate termination of a thread should be avoided like the plague but it seems to work I think.
The worker object that runs in the QThread uses std::shared_ptr for it's members through std::make_shared.
Are there still chances of memory leaks/corruption?
Apart from this, because I create my QThread in a method, I receive a warning from QT:
QObject: cannot create children for a parent that is in a different thread
Despite this warning, my code still runs but I have doubts. Is it safe to ignore this warning? What are the risks/consequences of ignoring this?
Is it safer to litter the server connecting code with QT's interruption checking points/rewrite it in boost using boost::interruption_point instead of calling terminate? i.e
sendData();
if (QThread::currentThread()->isInterruptionRequested())
{
return;
}
sendData();
if (QThread::currentThread()->isInterruptionRequested())
{
return;
}
...
Advice much appreciated thanks.

Should I receive all messages after QLocalSocket is disconnected?

I have an application in c++/Qt in Windows, Linux and MacOSX, and I have a local client-server mechanism using Qt Local Server/Socket.
When the server refuses a connection, I send a message and close the socket, using QLocalSocket::disconnectFromServer()
From the documentation I see
If there is pending data waiting to be written, QLocalSocket will enter ClosingState and wait until all data has been written.
So in the client side, I connect the signal QLocalSocket::disconnected and do the following in my slot
void MyClientClass::onSocketDisconnected()
{
qDebug() << "Socket disconnected";
socket->readAll();
//I do something with the data read
}
But it happens that sometimes, mostly on slow Linux machines (I try with virtual machines with only 1 processor), I do not receive the last message that the server send just before closing.
Why this happens? It should be in contrast with the documentation, shouldn't it?
Is there some motivation why I noticed it only in Linux and MacOSX (where Qt uses unix domain sockets) and I did not noticed it in Windows (where Qt uses pipes)?
Maybe there is some motivation related to domain sockets? Or I just misunderstood something?
Edit: as written in the comments below, in these cases when I do not receive the message, also the QLocalSocket::ClosingState is missing and I receive directly the QLocalSocket::UnconnectedState
Edit 2: as suggested in comments, I tried the waitForReadyRead() function. I did it onSocketDisconnected() and also onStateChanged() when the state goes to QLocalSocket::ClosingState or QLocalSocket::UnconnectedState. When I receive the QLocalSocket::ClosingState everything goes well, but the problem, as I said in the last edit, is that sometimes QLocalSocket::ClosingState is missing. In this case, the waitForReadyRead() fails without waiting the timeout and I have a warning "QIODevice:read (QTcpSocket): device not open" (even if I am using QLocalSocket, maybe the warning message is not updated well in Qt source). By the way, I am using Qt5.7.

SQLExecDirect doesn't return when deadlocked

I have a C++ app calling a stored procedure via SQLExecDirect. If there is a deadlock SQLExecDirect doesn't return until the deadlock is resolved.
I've read in the .net world it can detect deadlocks and throw an exception. Is there any way with C++/ODBC to regain control while deadlocked? I suspect the answer is no, but I'm hoping there's some ODBC feature I haven't found yet.
The only work around I can think of is kicking off another thread to run it and and setting a timeout for the thread to return.
And no, I can't fix the deadlock. This app is running queries or stored procedures from my customer's DBs that they choose. I just don't want it unresponsive for the duration of the deadlock.
If your ODBC provider supports asynchronous execution you could perform the operation that way, ODBC 3.8+ even supports an event-based notification mode over the older 3.0 polling-only. Note that unless using something like SQLServer's MARS your connection will still be deadlocked it just allows the thread to do something else while waiting for an answer.

Boost Asio Error

I've tried to see if anyone else if having this problem, but I haven't found anything online yet. Does anything in this code looks like I'm invoking boost incorrectly?
This code works when I am logged into the machine that is starting the TCP server, but fails when no one is logged in. I stripped the code down to only look at the boost asio logic.
//create _acceptor, which will eventually listen for incomming connections, asynchronously
_acceptor = boost::shared_ptr<tcp::acceptor>(new tcp::acceptor(*_io_service));
_acceptor->open(tcp::endpoint(tcp::v4(), _port).protocol());
_acceptor->set_option(tcp::acceptor::reuse_address(false));
//omitted logic find a port that is open
_acceptor->bind(tcp::endpoint(tcp::v4(), _port));
//omitted error handling logic if open port not found
//Start listening for incoming connections asynchronously.
_acceptor->listen();
sslSocketPtr ssl_socket(sslSocketPtr(new ssl::stream<ip::tcp::socket>(*_io_service, _sslContext)));
_acceptor->async_accept(ssl_socket->lowest_layer(),
boost::bind(&TCPServer::handle_sslAccept, shared_from_this(), boost::asio::placeholders::error, ssl_socket));
When no one is logged into the machine, the ssl_socket constructor throws the exception: "static_mutex: Access is denied".
If I define BOOST_ASIO_ENABLE_OLD_SSL the code works correctly, but I think that may be contributing to another bug in my code. So I am trying to use the latest SSL logic from Boost.
Any help would be appreciated!
I'm going to assume from the symptoms that you run on Windows.
On windows, static_mutex is implemented as a named (interprocess) mutex and gets "opened" using CreateMutexW:
If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object, GetLastError returns ERROR_ALREADY_EXISTS, bInitialOwner is ignored, and the calling thread is not granted ownership. However, if the caller has limited access rights, the function will fail with ERROR_ACCESS_DENIED and the caller should use the OpenMutex function.
As you can see you don't have the required permissions. However, you could still have this working if the mutex is always created by a privileged process. In that case you could modify the code that opens an existing named mutex with OpenMutex as the documentation hints.
It's likely easier to run the process under a user that has the required permissions thought

Issues using Mysql++ in a multithreaded environment

Hoping someone could help me out, as I'm getting some 'weird' segmentation faults. I'm currently working on a C++ daemon that periodically processes incoming data from an input source, and then sends it back to a different system.
The daemon currently runs two threads - one thread (main thread) that reads incoming data from a message queue and that inserts processed data into an MySQL database, and a second one that reads from a specific table and pushes processed data to a different system.
I'm assuming the error is somehow related to MySQL and threading, because I have no issues when running one thread (just the data processing, or just pushing back the processed data).
The SIGSEGV errors are all mysql++ related (the first mysql++ method that is called after connecting to the DB), eg:
(gdb) backtrace
#0 clear (this=0xabd4e8) at /usr/include/c++/4.7/bits/basic_string.h:801
#1 ping (this=0xabcf40) at ./lib/dbdriver.h:465
#2 mysqlpp::Connection::ping (this=<optimized out>) at ./lib/connection.cpp:243
The crash is also always triggered from the secondary thread, when both threads are connected to the MySQL database (runs fine when the main thread is running an artificial while(true) loop)
Connection code:
mysqlConnection = new mysqlpp::Connection(false);
mysqlConnection->set_option(new mysqlpp::ReconnectOption(true)); // Reconnect if session times out
if(!mysqlConnection->connect("fakeDbName", "fakeHostName",
"fakeUserName", "fakePassword))
{
printf("Failed to connect..\n");
}
if(!mysqlConnection->thread_aware())
{
printf("Mysql++ not compiled with threading support\n");
}
else
{
printf("Mysql++ compiled with threading support\n");
}
I followed the guidelines from Mysql++, configuring/compiling with '--enable-thread-check' and linking with 'libmysqlclient_r'. I'm getting a 'Mysql++ compiled with threading support' printf once connected. I'm also creating a separate connection object for both threads.
Any thoughts, anyone?
You could put a semaphore around your database access to rule out some thread-safety problem in the mysql library. But I'm curious why you need separate threads here... it seems like the action of the sending thread is tied directly to the receiving thread. Why can't you do both in the same thread?