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
Related
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.
I can't share code but theres a sort of example below. Here's my problem. Imagine I have a controller class that has an instance of QThreadPool. This class keeps a list of worker objects. When I start a runnable, I create a worker and give it to the runnable. The runnable operates each worker on the different threads. When the runnable is done, it fires a signal back to the controller object. The controller object then reads the results from the worker and deletes the worker. The controller keeps a list of all workers so that it can set the cancel flag on the worker, so that the thread can exit early if necessary.
The problem is that the QThreadPool will wait for all threads to finish when it's destroyed, which will be in the controller destructor. Since signals are queued when fired from the threads, then potentially canceling the workers in the controller destructor will queue the signals to be delivered to the controller. But since the controller will be in the context of the destructor, those signals won't hit the controller slots, and therefore the worker objects won't get destroyed.
Maybe I'm not dealing with the thread pool the way it should be. If I destroy the worker objects in the runnable, then there is potential for the worker to be destroyed before the another thread tries to cancel a worker. Can anyone recommend a good way of creating a cancelable thread pool?
class Controller : public QObject {
Q_OBJECT
public:
virtual ~Controller();
QThreadPool pool;
void startTask();
Q_SLOT void onWorkerDone(Worker * worker);
QList<Worker*> workers;
void cancelAll();
}
void Controller::startTask() {
Worker * worker = new Worker();
connect(pool, SIGNAL(done(Worker *)), this, SLOT(onWorkerDone(Worker *));
workers << worker;
pool.start(new Runnable(worker);
}
void Controller::onWorkerDone(Worker * worker) {
if ( worker ) {
// read worker...
delete worker;
}
}
Controller::~Controller() {
cancelAll();
// Destructor now kills pool object.
// The pool will wait until all threads complete.
// If there are any workers still running on the
// other threads, their done() signals will be
// queued to this instance, and since we're in
// the dtor, they won't make it to the slot,
// and worker won't get deleted.
}
void Controller::cancelAll() {
// loop the list and call cancel.
}
First mistake. You should not create a QThreadPool. This is application whide object so you should use QThreadPool::globalInstance()
If you want to cancel job you have to provide some functionality in Worker class to do so. You need some loop in Worker::run() method which will do your job and pool for value which should change tread safely when loop should finish.
The simple solution is to subclass QThreadPool and add an aboutToWait signal to that class. The signal would need to be emitted in the destructor. You can then hook up the signal to the controller's cancelAll() slot.
For this to work, the pool must be declared after the workers list!
Suppose you destroy the controller (this). The following happens:
Body of this.~Controller executes.
At the end, the object is still an instance of Controller. Now it has to be torn down into an instance of the base class. The members will be destructed in reverse of the order of declaration.
threadPool is destroyed first. threadPool.~MyThreadPool emits aboutToWait.
this.cancelAll runs, since it's directly connected. The call originates in the moc-generated implementation of the signal method. It lets the workers know that they should stop.
Remainder of threadPool.~MyThreadPool runs, and members (if any) are destructed in reverse order of declaration. this is now an instance of QThreadPool.
threadPool.~QThreadPool runs and waits for the workers to stop. As each worker stops, the controller.onWorkerDone is invoked, since it's directly connected to relevant thread pool's signals. Eventually, threadPool.~QObject runs the pool is fully destructed.
workers.~QList runs.
this.~QObject runs.
The controller is fully destructed.
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
I'm creating a worker thread in MFC with AfxBeginThread, but the thread is not getting scheduled. Here's the code:
CWinThread* worker = AfxBeginThread(initialUpdateWorkerThread, this);
DWORD dwExitCode = 0;
while(GetExitCodeThread(worker->m_hThread, &dwExitCode))
{
if(dwExitCode != STILL_ACTIVE)
break;
::Sleep(100);
}
When I run this, this loop just livelocks because initialUpdateWorkerThread is never called (I've put break points and message boxes at the top of it) so dwExitCode is always STILL_ACITVE. But if I put in a call to AfxMessageBox before the loop but after AfxBeginThread then the function is called. This makes me think that somehow I'm not calling the right function to get the thread scheduled, but a call to AfxMessageBox causes it to get scheduled.
How can I force the thread to be scheduled? I would think sleep would do that, but in this case it doesn't seem to.
Your worker thread is probably trying to send your main thread a message, but since you aren't processing messages on on the main thread, the worker thread simply waits. You can confirm this by simply breaking into the debugger to see what the worker thread is doing.
Is there a way to detect when a QT QRunnable object is done? (Other than manually creating some signalling event at the end of the run() method.)
You can simply use QtConcurrent to run the runnable and use a QFuture to wait for finished.
#include <QtConcurrentRun>
class MyRunnable : public Runnable{
void run();
}
in order to run and wait for it you can do the following
//create a new MyRunnable to use
MyRunnable instance;
//run the instance asynchronously
QFuture<void> future = QtConcurrent::run(&instance, &MyRunnable::run);
//wait for the instance completion
future.waitForFinished();
Qtconcurrent::run will start a new thread to execute method run() on instance and immediately returns a QFuture that tracks instance progress.
Notice however that using this solution you are responsable to keep instance in memory during the execution.
There might be, or you might have to go a slight bit higher-level. The QFuture and QFutureWatcher classes are designed to work with Qt's Concurrent framework, and the QFutureWatcher class has a signal when the item it is watching has finished.
You can add your own SIGNAL which gets emitted as the last thing that your run() method does. Then simply connect it to coreesponding SLOT right before calling connect(...);