So I have been stuck at this problem for a while now. For some reason, my application always crashes on close and this is the error message I get:
The inferior stopped because it triggered an exception.
Stopped in thread 0 by: Exception at 0x50c15a08, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance)
The stack shows the following:
QWidget::show Line: 7030
And this is what my main.cpp currently looks like:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
I have no clue why the crash is occurring.
A little background: This is a multi-threaded application (using both QThread and QtConcurrent). When the threads are NOT started, the application closes just fine. Hence I added the following check to ensure that the thread is being terminated properly but this is not helping:
void MainWindow::closeEvent(QCloseEvent *event)
{
if (thread->isRunning()) {
thread->terminate();
while(!thread->isFinished()){
}
event->accept();
}
}
EDIT: How the new thread was created
QThread *myThread = new QThread(this);
Worker *worker = new Worker(this, user, p);
worker->moveToThread(myThread);
connect(myThread, SIGNAL(started()), worker, SLOT(doWork()));
connect(worker, SIGNAL(workDone()), this, SLOT(deleteThread()));
myThread->start();
...and this is how I am handling the deletion of the thread after the download completes:
void MainWindow::deleteThread(){
worker->deleteLater();
myThread->quit();
while(!myThread->isFinished()){
}
myThread->deleteLater();
}
You should either listen for terminated signal from the thread or wait for the thread to terminate. Telling the thread to terminate doesn't block, so if you then immediately accept the close event you will get your exception.
This is described in more detail in the documentation for the terminate slot
Proper QThread stop code is:
myThread->quit();
myThread->wait();
Also you have used moveToThread(this);
You need to moveToThread back to parent thread first.
For example your code is:
moveToThread(this);
start();
You need to save currentThread() before moveToThread() like this:
QThread *savedThread=currentThread();
moveToThread(this);
start();
And before quit or terminate you need to restore it:
moveToThread(savedThread);
quit();
wait();
You can put it on destructor of course.
Related
I need to run a method in my MainWindow class, in a different thread as it is a length and time consuming process.
This is what I tried:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
initGui(ui);
// Create background worker thread
backgroundWorker = QThread::create([this] {
backgroundMethod();
});
// Define when finished with work
connect(backgroundWorker, &QThread::finished, [this] () {
qDebug() << "Background method has finished";
// Stop movie
ui->lblLoading->movie()->stop();
// go to next screen
ui->tabbarMainWidget->tabBar()->setCurrentIndex(1);
//show backup icon files
if(filesToBackup.size() > 0) {
qDebug() << "There are files to backup!";
ui->lblInfoImage->show();
}
});
// Start worker thread
backgroundWorker->start();
}
backgroundMethod
void MainWindow::backgroundMethod() {
for (int i = 0; i < 10; i++) {
qDebug() << "Hello World";
}
}
I am omitting alot of code as it is not necessary. The basic logic is as follows:
Start new thread using QThread::create()
Run the backgroundMethod() until completed while having the UI free for other work.
When the backgroundMethod() has finished, the QThread should emit the finished() signal.
I have a connection setup between the backgroundWorker thread's finished() and the lambda to run some more code.
The problem:
Background method has finished
QObject::killTimer: Timers cannot be stopped from another thread
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x2801d950. Receiver 'lblInfoImage'
(of type 'QLabel') was created in thread 0x0x2688c4b0", file
kernel\qcoreapplication.cpp, line 578 04:11:28: The program has
unexpectedly finished.
In short, I am accessing the lblInfoImage on the backgroundWorker thread. I understood that using the signal/slot mechanism should cater for this issue, where my use of it is correct.
I am not sure why this is happening, I need some help in understanding what I did to cause the problem and how I can fix it
The problem is simple: you execute UI code on a non-UI thread which is strictly forbidden in Qt (and in many other UI frameworks across different languages). That happens because you do the connection wrong:
connect(backgroundWorker, &QThread::finished, [this] () {
...
});
That connection means: whenever QThread emits a finished signal run this function. The thing is, it will run the function in the context of the emitted signal which is another thread not the thread backgroundWorker lives in. So you have to provide the UI thread context for receiving this signal:
connect(backgroundWorker, &QThread::finished, this, [this] () {
...
});
Now the function provided will be executed in the context of the UI thread (this).
I'm trying to implement a multithreaded app that displays video using the OpenCV libraries (following the example given here).
I create two threads from the GUI thread that successfully terminate when the MainWindow is closed. However, the program still keeps on running (I have to use the stop button on the application output panel to close it down).
Here's my destructor for the MainWindow
MainWindow::~MainWindow()
{
captureThread.quit();
converterThread.quit();
if (captureThread.wait())
qDebug() << "Capture Thread has exited successfully";
if (converterThread.wait())
qDebug() << "Converter Thread has exited successfully";
delete ui;
}
The Application Output window returns the following output on both the Debug and Release builds
Capture Thread has exited successfully
Converter Thread has exited successfully
However, the application only quits in Debug mode.
From what I have gathered from a few google searches is that the application continues on running IF there is a thread that has not been properly terminated. Can that be the case here? If yes, then how may I know which other thread is also running in the program, so that I may terminate/quit it?
Using Qt 5.4 with MSVC 2013 and OpenCV 3.0 beta on Win 8.1
Edit
I create my threads in MainWindow constructor
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// registers the type cv::Mat. After a type is registered, one can create/destroy objects at runtime
qRegisterMetaType<Mat>();
// Initializing class' instance
Capture* capture = new Capture;
Converter* converter = new Converter;
ui->labelFrame->setAttribute(Qt::WA_OpaquePaintEvent);
converter->setProcessAll(false);
capture->moveToThread(&captureThread);
converter->moveToThread(&converterThread);
converter->connect(capture, SIGNAL(matReady(Mat)), converter, SLOT(processFrame(Mat)));
this->connect(converter, SIGNAL(imageReady(QImage)), this, SLOT(setImage(QImage)));
// thread clean up
connect(&captureThread, SIGNAL(finished()), &captureThread, SLOT(deleteLater()));
connect(&converterThread, SIGNAL(finished()), &converterThread, SLOT(deleteLater()));
QObject::connect(capture, &Capture::started,
[](){ qDebug() << "capture started"; });
QMetaObject::invokeMethod(capture, "start");
captureThread.start();
converterThread.start();
Edit 2 : I modified my main.cpp to this
QApplication a(argc, argv);
MainWindow w;
w.show();
int ret;
ret = a.exec();
qDebug() << "QApplication.exec() returns " << ret;
return ret;
and I received the following message in the Application output window
QApplication.exec() returns 0
Capture Thread has exited successfully
Converter Thread has exited successfully
which is confusing, since the QApplication should quit after the threads have been stopped. so I moved the thread cleanup to the abouttoQuit() slot. The order of exiting has changed by this modification but the original problem remains. (The wrong order could be due to the implementation of the qDebug() function, but thats just me guessing)
PS I even added captureThread.terminate() and converterThread.terminate() in the destructor but still the results are the same.
Problem
Ok so it turned out to be a memory leak. In the constructor of my MainWindow, I had declared and initialized two instances of converter * and capture * classes. However, when the constructor ended its scope, these pointers were never freed.
Solution
Free the memory in the CleanUp() function. (The CleanUp() function is connected to the aboutToQuit() slot of the application. To make the pointers accessible to the CleanUp() function, declare them as members of the MainWindow class.
QMetaObject::invokeMethod(capture, "start");
Looks suspicious. Can you replace it with:
connect(&captureThread, &QThread::started, capture, &Capture::start);
Also, no need to do thread clean up, because they are members of MainWindow class and will be destroyed with it, remove those two lines:
connect(&captureThread, SIGNAL(finished()), &captureThread, SLOT(deleteLater()));
connect(&converterThread, SIGNAL(finished()), &converterThread, SLOT(deleteLater()));
This is my main.cpp which starts the mainwindow:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TabWindow w;
w.show();
return a.exec();
}
Even with the a.connect(...) I do not understand why myApplication.exe still runs after I close the mainwindow. Any suggestions on how I can fully end all processes after the quit button is clicked?
EDIT: The Qt Documentation says this:
We recommend that you connect clean-up code to the aboutToQuit() signal, instead of putting it in your application's main() function. This is because, on some platforms, the QApplication::exec() call may not return.
There's nothing wrong with your code. And your connect doesn't do anything.
Unless you call QGuiApplication::setQuitOnLastWindowClosed(true) somewhere, application should exit when the last window is closed. Probably you block event loop somewhere in your window code.
Thanks to the comment posted by #ratchetfreak in my question, I figured out where the problem was.
In my MainWindow, I started a worker thread which was not terminated and thus still persisted as a process after the application was closed. In order to fix this, I registered the close event and kept track of the existence of the thread - i.e. basically, ignored the closeEvent until the thread was deleted as well.
void MainWindow::closeEvent(QCloseEvent *event)
{
if (workerThreadExists) {
// Gracefully exiting all tasks inside the worker thread
while (workerThreadExists){
event->ignore();
}
event->accept();
}
}
...and for me workerThreadExists is just a BOOLEAN that is set to true once the thread is created and then it is set to false when the thread is deleted. Hope this helps!
You should have something like this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TabWindow w;
w.show();
return a.exec();
}
// Do quit in your TabWindow:
TabWindow::TabWindow()
: public QWidget(NULL)
{
connect( ui->myQuitButton, SIGNAL( clicked() ), qApp, SLOT( quit() ) );
}
just replace
return a.exec();
with
return 0;
That should end all processes which is associated with that program.
In the example below (inside Qt GUI application) a new thread is started (with an event loop in which I want some work to be done):
void doWork()
{
QThread* workerThread = new QThread();
Worker* worker = new Worker();
worker->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), worker, SLOT(startWork()));
connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
}
startWork() can be a long running operation during which the application can be closed.
I expected that the application will not be closed as long as startWork() is being executed on the workerThread. It seems though, that when I close the last application window, the workerThread is gone instantaneously (during long running operation) and application closes without problems.
The questions arose:
Why was the workerThread wiped right away?
Is it some parent/child issue?
How Qt handles such situation?
Is it programmer mistake, not to call wait() on QThread (eventually)?
Even if so, I tried to wait() inside a slot for aboutToQuit() and application wasn't closed after long running operation was done (with setup as above). Only quit(); wait(); (inside the slot mentioned) allowed the application to close. Why?
QThread has, basically, a long-standing API bug: it isn't always in a destructible state. In C++, an object is considered to be in destructible state when it's safe to invoke its destructor. Destructing a running QThread is an error. A QThread is merely a thread controller, it's not the "thread" itself. Think of how QFile acts: you can destruct it at any time, whether it's open or not. It truly encapsulates the notion of a file as a resource. A QThread is too thin of a wrapper around the native (system) thread: when you destruct it, it does not terminate nor dispose of the native thread if there is one. This is a resource leak (threads are OS resources), and people trip over this issue over and over again.
When the application's main() function returns, your implementation of the C/C++ runtime library happens to terminate all of the application's threads, effectively terminating the entirety of the application. Whether this is the behavior you desire is up to you. You're supposed to quit() and wait() your event-loop-running thread. For threads without an event loop, quit() is a no-op and you must implement your own quit flag. You must wait() on the thread before you destruct it. This is to prevent race conditions.
Below is a safe wrapper for QThread. It is a final class, since you can't reimplement run. This is important, since a reimplementation of run could be done in such a way that makes quit a no-op, breaking the contract of the class.
#include <QThread>
#include <QPointer>
class Thread : public QThread {
using QThread::run; // final
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { quit(); wait(); }
};
class ThreadQuitter {
public:
typedef QList<QPointer<Thread>> List;
private:
List m_threads;
Q_DISABLE_COPY(ThreadQuitter)
public:
ThreadQuitter() {}
ThreadQuitter(const List & threads) : m_threads(threads) {}
ThreadQuitter(List && threads) : m_threads(std::move(threads)) {}
ThreadQuitter & operator<<(Thread* thread) {
m_threads << thread; return *this;
}
ThreadQuitter & operator<<(Thread& thread) {
m_threads << &thread; return *this;
}
~ThreadQuitter() {
foreach(Thread* thread, m_threads) thread->quit();
}
};
It could be used as follows:
#include <QCoreApplication>
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
QObject worker1, worker2;
Thread thread1, thread2;
// Style 1
ThreadQuitter quitter;
quitter << thread1 << thread2;
// Style 2
ThreadQuitter quitterB(ThreadQuitter::List() << &thread1 << &thread2);
//
worker1.moveToThread(&thread1);
worker2.moveToThread(&thread2);
thread1.start();
thread2.start();
QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
return app.exec();
}
Upon return from main, the thread quitter will quit() all worker threads. This allows the threads to wind down in parallel. Then, thread2.~Thread will wait for that thread to finish, then thread1.~Thread will do the same. The threads are now gone, the objects are threadless and can be safely destructed: worker2.~QObject is invoked first, followed by worker1.~QObject.
1) Is it parent / child issue?
Not in the case of your code - You're not parenting the QThread. Qt doesn't like you to just terminate the main thread if you've other threads running. You're likely to see it complain in the standard output that the other thread was still running when the application was terminated. However, Qt will kill the other thread, which is why there's a function to call and wait for the thread to terminate properly.
2) Is it programmer mistake not to call wait()?
Yes. If you're having issues with the Thread not quitting properly, it's because you're not handling it correctly, in which case you could open another question and show the code as to how you're handling the wait before quitting.
when I close the last application window, the workerThread is gone instantaneously
Note that there's a function in QApplication called setQuitOnLastWindowClosed, which you can set to false, to prevent the app automatically quitting on closing the last window.
I got a program in which I connect with a QSignalMapper multiple signal from object to a slot in the main program:
class A()
{
private:
QSignalMapper * signalMapperRead_;
std::vector<Service*> services_;
public:
void initConnection()
{
signalMapperRead_ = new QSignalMapper();
connect(signalMapperRead_, SIGNAL(mapped(int)), this, SLOT(readyToSendToService(int)));
for ( size_t i = 0 ; i < services_.size() ; ++i )
{
connect(services_.at(i), SIGNAL(readyToSendToServer()), signalMapperRead_, SLOT(map()));
signalMapperRead_->setMapping(services_.at(i), (int)i);
}
}
int run()
{
initConnection();
for(;;)
{
//do stuff;
}
}
};
int main()
{
QApplication app(argc, argv);
A * a = new A();
a->run();
return app.exec
}
then, as the program is a kind of server i make him loop, and waiting for new client, ...
But the slot is never called. I am thinking that maybe it's because the program is always in the loop and never check if a signal has been emitted.
Can you please help me
Don't use your own loop, create a QApplication and call its exec() method.
You have to call QApplication::exec() for Qt to deliver signals.
Edit for changed code: Just remove the for(;;)-Loop, it's uneccessary. QApplication::exec() has its own loop.
But the slot is never called.
The Qt documentation about QApplication::exec says:
Enters the main event loop and waits until exit() is called [...].
It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. [...]
Generally, no user interaction can take place before calling exec(). [...]
This means that it's the exec method that takes care of the signal-slot system. You are calling A::run (before the exec function) which contains an for(;;) infinite loop which will block the real loop from being executed leading to your signals to be lost.
I have found a work-around. Beside I am not sure it's very efficient, my solution is to start a QEventLoop at every cycle of my for(;;) loop, and I made this QEventLoop quit on a QTimer timeout