[Interest] Evaluating the results of QSqlQuery across different threads resulting in memory leaks

mike neuhaus mike--p at hotmail.com
Mon Dec 11 22:39:39 CET 2017


Hi,

An application I'm currently working on is interacting with a SQLite database for loading GUI components like images, buttons, texts, etc. It is also using it for different things like user settings, which usually resides in a different thread than the GUI thread. In a sense the application is using the QtSqlite module wrong, because it is sharing a connection between threads. To solve issue I created a SQL serializer which, the name implies, serializes all queries through one thread which has its own local database connection. How it basically works is that any thread can enqueue a SQL query string into a message queue. The serializer will then process the queries one by one and notifies the thread which requested a query to be processed once the execution is finished.

When a thread is scheduling a query to be processed we simply call a function which takes care of (thread-safe) putting the request in our message queue and returns an object, which I call SqlReply. The user can then connect a SLOT to the finished SIGNAL of this object, or the user can call a blocking function, which will block until the query is processed by the serializer. Once the serializer starts processing the request, the software creates a local QSqlQuery object on the serializer thread. This QSqlQuery object is used to execute the query string which was scheduled by another thread. Once the execution is finished successfully, we copy and assign the local QSqlQuery object to another QSqlQuery object which resides inside the SqlReply. After that we delete the local copy inside the serializer thread and call the finished signal of the SqlReply object, or wake up our wait condition in the blocking function. Once we return from the blocking function of the SqlReply object (or the connected SLOT is called), we can call a function on the SqlReply object which will return the QSqlQuery object we previously copied and assigned from the serializer thread (so basically we moved the executed QSqlQuery object from the serializer thread to the thread which initially created the query request). So far this is working fine, however when we delete the SqlReply (and effectively the last reference to the QSqlQuery object, I verified that the reference counter is indeed '1' at this point) the resources allocated for the execution of the query string are not being free'd. I'm not sure why this is forming a problem as the query is created in the same thread where I created my database connection. However it might problematic if the results are not cached after until I actually retrieve values from the QSqlQuery. Because the retrieval of values will always happen on a different thread (we copied the QSqlQuery object created in the serializer thread to thread where we created the SqlReply). Can someone confirm that the way I'm currently doing this is indeed not supported by QT and/or the underlying SQLite driver?

Note:
I can cache the results and give back those cached results to the other threads, instead of using the QSqlQuery class. However, because the current program is using the QSqlQuery class extensively I'd like to remain using that over the cached results to minimize changes in the current software.

Regards,

Mike Neuhaus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20171211/a199d943/attachment.html>


More information about the Interest mailing list