QThread is creating a memory leak - multithreading

After much testing and changes to my QT application, Visual Leak Detector identified the source of a pesky leak (8 bytes). VLD reported the QT application is clean except for a QThread* pointer.
A bit of implementation background: the application is modelled as a hybrid of solution by Jeffrey Holmes, Bulk download of web pages using Qt. Thanks to Jeffrey for the earlier solution!
Questions:
Why is QThread* not destroying itself when the worker thread completed its work?
How can I force the QThread* to delete the thread and worker object when work is complete?
Should QThread be implemented differently?
Code:
void vqMDIChildDialog::processWorkQueue(bool bIsBC)
{
if (m_listOfTables.isEmpty() && currentReplicationThreads == 0)
{
}
else if (!m_listOfTables.isEmpty())
{
for (int i = 0; i < maxReplicationThreads && !m_listOfTables.isEmpty();i++)
{
QThread *thread = new QThread;
QPointer<vcSharedDataQt> worker = new vcSharedDataQt();
worker->moveToThread(thread);
QString tmpTableName (m_listOfTables.dequeue());
worker->setParentObject(this);
//
// set properties on the worker object.
//
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread,SLOT(deleteLater()));
connect(worker,
SIGNAL(updateMessageFromThread( const QString&,
const QString&,
const QString&,
const QString&,
const QString&,
const QString&,
const QString&)),
this,
SLOT(UpdateStatusBarFromThread( const QString&,
const QString&,
const QString&,
const QString&,
const QString&,
const QString&,
const QString&)));
thread->setObjectName(worker->getUniqueKey());
thread->start();
currentReplicationThreads ++;
}
}
}
Stack would not permit me to answer this question so:
The function was protected with a QMutex:
mutex.lock();
processWorkQueue();
mutex.unlock();
This caused the memory leak. QThread apparently could not be destroyed on worker thread completion. I removed the mutex and VLD is reporting no memory leaks with QThread.

A QThread doesn't really know when its work is done. You can answer your own question by thinking of how you would implement this.
Its run() method simply spins an event loop. Since all an event loop can know is if there are any events posted to it, the only condition you could reasonably implement is to quit the thread when there are no further events. This would make a thread quit immediately, so it's not helpful at all.
Perhaps you'd wish to terminate the thread when there are no more QObjects that have the thread as their thread. This could certainly be implemented as an optional behavior in QThread, but whether it's a change that would get accepted I don't know. It must not be a default behavior, since in many situations constant destruction and re-creation of threads is simply wasteful - one might want to retain a thread that has no objects on it.
Ultimately only you know when the thread's work is done. Your worker object can invoke thead()->quit() or it can emit a signal when it's done - like you do already.
A QThread cannot destroy itself when the work is done, since threads are restartable. You have full control over thread's lifetime, so you certainly can destroy it when its work is done, and you do already, only you do it wrong.
Your problem is really in the order that you wish for things to happen. The deleteLater operation is performed by the event loop. If a thread's event loop isn't running, the deleteLater is a NO-OP.
So, first of all, your connections should be done such that they form a cascade that can only execute in a well-defined order:
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(worker, SIGNAL(destroyed()), thread, SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
Then, you must ensure that the thread where your processWorkQueue method runs is not blocked and has a chance for its event loop to proceed. It's this event loop that will process thread's deletion.
As noted by AlexP, this doesn't work in Qt 4.7 or earlier, since all those versions had a bug in QThread's implementation. "QThread's behavior has changed" is an euphemism for "there was an ugly bug that finally fixed".
Your connect is overly verbose. You can drop spaces and reference/const-reference from the signature. The third argument is also optional if it's this. It should look like:
connect(worker,
SIGNAL(updateMessageFromThread(QString,QString,QString,QString,
QString,QString,QString)),
SLOT(updateStatusBarFromThread(QString,QString,QString,QString,
QString,QString,QString)));

Answers:
Why is QThread* not destroying itself when the worker thread completed its work?
Because there are different ways to use QThread in which at least one must be able to query thread states or class members after worker has finished. Also the thread may be restarted.
How can I force the QThread* to delete the thread and worker object when work is complete?
The finished signal should be enough for you to call a slot deleting both.
Should QThread be implemented differently?
There are different implementations for different situations. http://qt-project.org/doc/qt-5.0/qtcore/thread-basics.html

Related

Deleting Qthread on the middle of running

I created a thread with class A and after deleted class A, the thread is not deleted. It continues running.
I explicitly called the thread destructor, quit and exit function but still, the thread did not stop running.
Is there any thing like KILL function to stop the thread execution
void A::init()
{
WorkerThread *Thread = new WorkerThread(this);
}
void B::slotClose()
{
A *obj = getObj();
if(obj)
{
m_pScene->removeItem(obj);
obj->deleteLater(); // this calls thread distructor also but thread execution is not stopping
}
}
From the docs:
Note that deleting a QThread object will not stop the execution of the thread it manages. Deleting a running QThread (i.e. isFinished() returns false) will result in a program crash. Wait for the finished() signal before deleting the QThread.
You should never delete a running QThread object.
So I think it would be the best for you to write some termination/quitting logic in your WorkerThread, expose some slot for example quit and connect signal with this quit slot.
If you just want to terminate the thread no matter what, just connect destroyed SIGNAL to terminate SLOT (http://doc.qt.io/qt-5/qthread.html#terminate)
So assuming your A class derives from QObject, what would you do inside this class is:
connect(this, SIGNAL(destroyed()), Thread, terminate());
If you have your own slot quit exposed, so you make sure you properly stop all that's executing in your loop just instead terminate() use quit().
connect(this, SIGNAL(destroyed()), Thread, quit());
Here's an example of implementing such a logic: http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
Or just put quit = true in your ThreadWorker destructor.
It should be straightforward. Good luck!
Also some official documentation with examples (imo doing it right):
https://wiki.qt.io/QThreads_general_usage
https://doc.qt.io/archives/qt-5.8/qtnetwork-blockingfortuneclient-example.html
https://doc.qt.io/archives/qt-5.8/qtcore-threads-mandelbrot-example.html

How to unblock a QThread running a pcsc call?

I have a Qt application that connects to a card reader using various pcsc implementations under GNU/Linux, MacOS, and Windows. All communication with the card runs in a worker thread.
In one scenario, the user starts an operation requiring communication with the card via a card reader. The card reader has a keyboard and during the authentication procedure the user must enter their PIN on the reader's keyboard.
This operation is implemented by a call to SCardControl() (see e.g. the Microsoft documentation). As long as the user is working with the reader, the call to SCardControl() does not terminate and the worker thread is blocked by it.
At this point, the user might decide to close the application while the operation is still pending. Closing the application at this point causes the application to crash (on Linux with signal SIGABRT) because:
The worker thread is blocked waiting for SCardControl() to return.
The main thread cannot stop the blocked thread: neither quit() nor terminate() cause the thread to finish.
When the application is exited, the QThread object for the worker thread is destroyed and, since the thread is still running state, it throws a signal to indicate an error.
I have tried several solutions.
Subclass QThread and create a worker thread which calls setTerminationEnabled(true); to allow termination through QThread::terminate(). This does not work on MacOS: when QThread is destroyed, the thread is still in a running state and the signal SIGABRT is emitted.
Handle signal SIGABRT on shutdown and ignore it. This did not seem to be a good idea but I wanted to try it out before discarding it. After ignoring signal SIGABRT, a signal SIGSEGV is received and the application crashes. I had adapted the approach described here.
Try to unblock the thread by sending a command to the card reader from the main thread. I tried SCardCancel(), SCardDisconnect() and SCardReleaseContext() but none of these commands has any effect on the blocked thread.
I find it quite strange that it is not possible to cleanly shutdown an application when a thread is blocked on some function call, but all the solutions I have tried have not worked and I have run out of ideas. Did I overlook something? Does anybody have any useful hint?
EDIT
I looked into the Qt source code for QThread and found out that on Unix-like platforms QThread::terminate() uses pthread_cancel() internally. But apparently pthread_cancel() does not work / does nothing on Darwin, see e.g. here and here.
So, maybe I will really have to go with the option of showing a dialog to the user asking to remove the card from the reader.
Cleanly shutting down a thread is not possible from outside if it is blocked in a call. You can, however, prevent user from quitting the application before the operation has completed.
void MainWindow::closeEvent(QCloseEvent *closeEvent) {
if (workerBlocked) closeEvent->ignore();
}
In addition, you can show a dialog telling the user the operation has to be completed first.
Also, if possible, you can let the window close but keep the application alive until the operation is complete by setting qApp->setQuitOnLastWindowClosed(false);
The problem boils down to the fact that a QThread object isn't destructible while the associated thread is running. Usually, it would a print statement like this to the debug output:
QThread: Destroyed while thread is still running
Don't agonize over trying to get SCardControl to return so that the worker thread can be quit safely (since it doesn't return as long as the user is interacting with the reader). Instead, You can follow this answer to destruct the QThread object in a safe manner with a minimum amount of changes to your current implementation.
Here is an example that shows what I mean:
#include <QtWidgets>
//a thread that can be destroyed at any time
//see http://stackoverflow.com/a/25230470
class SafeThread : public QThread{
using QThread::run;
public:
explicit SafeThread(QObject* parent= nullptr):QThread(parent){}
~SafeThread(){ quit(); wait(); }
};
//worker QObject class
class Worker : public QObject {
Q_OBJECT
public:
explicit Worker(QObject* parent = nullptr):QObject(parent){}
~Worker(){}
Q_SLOT void doBlockingWork() {
emit started();
//the sleep call blocks the worker thread for 10 seconds!
//consider it a mock call to the SCardControl function
QThread::sleep(10);
emit finished();
}
Q_SIGNAL void started();
Q_SIGNAL void finished();
};
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
//setup worker thread and QObject
Worker worker;
SafeThread thread;
worker.moveToThread(&thread);
thread.start();
//setup GUI components
QWidget w;
QVBoxLayout layout(&w);
QPushButton button("start working");
QLabel status("idle");
layout.addWidget(&button);
layout.addWidget(&status);
//connect signals/slots
QObject::connect(&worker, &Worker::started, &status,
[&status]{ status.setText("working. . .");} );
QObject::connect(&worker, &Worker::finished, &status,
[&status]{ status.setText("idle");} );
QObject::connect(&button, &QPushButton::clicked, &worker, &Worker::doBlockingWork);
w.show();
return a.exec();
}
#include "main.moc"
Notice that the SafeThread's destructor makes sure to wait() until the associated thread has finished execution. And only afterwards, the main thread can proceed to call QThread's destructor.

ensuring that all threads finish before JVM completely terminates

Let's say I have a SwingWorker object and it's still in its doInBackground() method. If a user calls system.exit(0)...how do I best ensure that the SwingWorker daemon/worker thread completes? I imagine that I have to do this manually. The best idea I have at the moment is to call join() on all outstanding worker threads in/on the same thread that calls System.exit(0)...is this correct?
AND, if using join() is a good idea...should I use it in some sort of while loop in the case that the thread calling join() has spurious activity?
For instance:
//pseudocode
Vector<Thread> threadsThatMustFinishBeforeTerminatingJVM = new Vector<Thread>();
Thread closingThread = new Thread(){
public void run(){
for(Thread t: threadsThatMustFinishBeforeTerminatingJVM){
// closingThread waits for t to finish, (is this *really* safe?)
t.join();
}
System.exit(0);
}
}
closingThread.start();
Is this at all correct?
Take a look here
"The System.exit method forces termination of all threads in the Java virtual machine."
If you call system.exit you're basically saying, "exit now, I don't care what's going on." If you want to shut down cleanly you're going to need to set us some kind of coordination/synchronization between your threads.
If your doInBackground method is still active you could wait until it completes before exiting, some synchronization primitive, shared lock, or some such.
You can add some logic in the done() method of your SwingWorker that would allow an exit.
The better way is probably to query getState() on your SwingWorker. It'll return DONE if the task has completed and if so you can exit, otherwise just wait.

Disabling a System.Threading.Timer instance while its callback is in progress

I am using two instances of System.Threading.Timer to fire off 2 tasks that are repeated periodically.
My question is: If the timer is disabled but at that point of time this timer is executing its callback on a thread, then will the Main method exit, or will it wait for the executing callbacks to complete?
In the code below, Method1RunCount is synchronized for read and write using lock statement ( this part of code is not shown below). The call back for timer1 increments Method1RunCount by 1 at end of each run.
static void Main(string[] args)
{
TimerCallback callback1 = Method1;
System.Threading.Timer timer1 = new System.Threading.Timer(callback1,null,0, 90000);
TimerCallback callback2 = Method2;
System.Threading.Timer timer2 = new System.Threading.Timer(callback2, null, 0, 60000);
while (true)
{
System.Threading.Thread.Sleep(250);
if (Method1RunCount == 4)
{
//DISABLE the TIMERS
timer1.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
timer2.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
break;
}
}
}
This kind of code tends to work by accident, the period of the timer is large enough to avoid the threading race on the Method1RunCount variable. Make the period smaller and there's a real danger that the main thread won't see the value "4" at all. Odds go down considerably when the processor is heavily loaded and the main thread doesn't get scheduled for while. The timer's callback can then execute more than once while the main thread is waiting for the processor. Completing missing the value getting incremented to 4. Note how the lock statement does not in fact prevent this, it isn't locked by the main thread since it is probably sleeping.
There's also no reasonable guess you can make at how often Method2 runs. Not just because it has a completely different timer period but fundamentally because it isn't synchronized to either the Method1 or the Main method execution at all.
You'd normally increment Method1RunCount at the end of Method1. That doesn't otherwise guarantee that Method1 won't be aborted. It runs on a threadpool thread, they have the Thread.IsBackground property always set to true. So the CLR will readily abort them when the main thread exits. This again tends to not cause a problem by accident.
If it is absolutely essential that Method1 executes exactly 4 times then the simple way to ensure that is to let Method1 do the counting. Calling Timer.Change() inside the method is fine. Use a class like AutoResetEvent to let the main thread know about it. Which now no longer needs the Sleep anymore. You still need a lock to ensure that Method1 cannot be re-entered while it is executing. A good way to know that you are getting thread synchronization wrong is when you see yourself using Thread.Sleep().
From the docs on System.Threading.Timer (http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx):
When a timer is no longer needed, use the Dispose method to free the
resources held by the timer. Note that callbacks can occur after the
Dispose() method overload has been called, because the timer queues
callbacks for execution by thread pool threads. You can use the
Dispose(WaitHandle) method overload to wait until all callbacks have
completed.

Suspend main thread in qt

I want to make a function that stops the main thread and restarts restarts it after a couple of seconds. I tried the following:
void Mainwindow::timeout()
{
QTimer timer;
timer.setSingleShot(true);
timer.setInterval(time*1000);
connect(&timer,SIGNAL(timeout()),MainWindow::thread(),SLOT(start()));
timer.start();
SuspendThread(MainWindow::thread());
}
Unfortunately this doesnt do a whole lot... Any tips?
Maybe I am overlooking something, but a "function that stops [...] and restarts after a couple of seconds" sounds like sleep() to me. Let the OS do the timing instead of re-inventing the wheel.
Or is there any reason you can't post some message to the main thread? In this simple use case maybe even via a single mutex would be enough. Set the mutex from another thread, check it in the main threads event loop and possibly call sleep() directly.
That also eases debugging, as you have a single place the main thread will go sleeping willingly instead of being suspendend on the fly by other threads.
your timer object is destroyed at the end of the the Mainwindow::timeout() function, so it will never emit its timeout() signal.
I am not sure why you would want to stop event loop, but you can sleep your thread by waiting on locked mutex for x milliseconds.
In the code below you will use waitCondition.wait(&mutex, msecs); to wait on a condition variable for maximum msecs milliseconds. Since mutex is locked, as there is no another thread which will send wake up signal, this will block your thread for timeout milliseconds. Reference is here.
#include <QWaitCondition>
#include <QMutex>
class Sleep
{
public:
static void msleep(unsigned long msecs)
{
QMutex mutex;
mutex.lock();
QWaitCondition waitCondition;
waitCondition.wait(&mutex, msecs);
mutex.unlock(); // Not necessary since new mutex will always be created,
// but since destroying locked mutex
// is bringing undefined behavior, let's follow some ethics
}
};

Resources