Is this a correct way terminate the thread ...
if(m_ReviewImageThreadLoader !=NULL)
{
m_ReviewImageThreadLoader->quit();
m_ReviewImageThreadLoader->wait();
m_ReviewImageThreadLoader->terminate();
delete m_ReviewImageThreadLoader;
m_ReviewImageThreadLoader = NULL;
qDebug()<<"m_ReviewImageThreadLoader closed"<<endl;
}
... where m_ReviewImageThreadLoader is the thread object.
The answer to your question depends to a large extent on the nature of the work being done on your thread. If the usage is something like...
QThread *m_ReviewImageThreadLoader = new QThread;
MyObject *mo = new MyObject;
mo->moveToThread(m_ReviewImageThreadLoader);
m_ReviewImageThreadLoader->start();
then your code should be fine (although you really shouldn't need the call to terminate()).
If, on the other hand, m_ReviewImageThreadLoader is of a type derived from QThread and has explicitly overridden QThread::run then you'll need to supply more information before your question can be answered.
Have you tried your code? Does it appear to work?
Related
I have an annoying issue with Qt and multi threading. Below I have created some simplified code. In my real code, the principle is exactlty the same but way too complex hence for using a simplified version.
The problem is that the application randomly crashes during different points at the run-time with different messages:
free(): invalid pointer
double free or corruption
The crash is triggered from within Qt, I will explain at the end of the post.
Here is how the code works.
So, I have classA that starts a thread:
class classA
{
public:
void start();
boost::function<void (std::string)> __ptr; // for callback
private:
boost::thread * thread;
void run();
};
void classA:start()
{
thread = new boost::thread(&classA::run, this); // start the thread
}
and here is the actual method that runs in the separate thread:
void classA::run()
{
for (int i = 0; i < 50000; i++)
{
static int count = 0;
__ptr("test123" + std::to_string(++count));
}
}
In my QDialog inherited class, I have a simple method that assigns the boot::function so I have declared another boost::function ptr. The problem is not with the ptr, it is with Qt, read on, the call back works just fine...
class myClassB : public QDialog
{
Q_OBJECT
public:
explicit myClassB (QWidget *parent);
classA ca;
private:
boost::function<void (std::string)> __ptr;
void mycallback(std::string);
};
In the constructor of myClassB, I am assigning my call back to boost::function like this (like I said, the callback works fine).
myClassB::myClassB()
{
this->__ptr = ( boost::bind( &myClassB::mycallback, this, _1 ) );
ca.__ptr = __ptr;
}
Here is where the problem starts. In my callback within my classB QDialog, I emit a Qt signal
void myClassB::mycallback(std::string txt)
{
emit sig_qt_data_received(txt);
}
This signal gets connected in my classB's constructor:
connect(this, SIGNAL(sig_qt_data_received(std::string)), this, SLOT(data_received(std::string)), Qt::DirectConnection);
and finally, the implementation of the Qt slot:
void myclassB::data_received(std::string txt)
{
ui->lbl_status->setText(txt);
}
This is where the problem is:
If you remove ui->lbl_status->setText(txt);, the program works flawlessly, it never crashes, if you leave it, it randomly crashes:
free(): invalid pointer
double free or corruption
It appears that the problem is within Qt as when I remove the setText() references, it does not crash and I have followed just about every GUI multi-threading procedure I have found and I don't know what I am doing wrong.
To connect the Qt signal, I am using Qt::DirectConnection and if I use Qt::AutoConnection it will work without a crash but sometimes the whole UI freezes (Edit: this is incorrect, see my answer).
I hope someone can help. If you need more code / real code, let me know, I will write an actual runnable code that you can run and compile but the fundamentals are the same, that's how the code works.
I don't want to be using QThread.
Resolved! Qt::DirectConnection was the culprit, now I use Qt::AutoConnection and it never crashes and according to the docs it is the default:
(Default) If the receiver lives in the thread that emits the signal,
Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used.
The connection type is determined when the signal is emitted.
G.M's response above gave me the hint (Thanks):
the fact that explicitly specifying the connection type as
Qt::DirectConnection changes the behaviour suggests you've almost
certainly got a race condition due to threading
Also thank you jpo38 for suggesting / replying anyway.
Now I know I said sometimes it would freeze but no, that's incorrect, it never freezes, I had confused things.
Consider functions like below:
class1::class1()
{
class3 obj3 = new class3(this);
}
void class1::function1()
{
class2 *obj2 = new class2();
connect(obj3, SIGNAL(sig()), obj2, SLOT(slt()));
}
void class3::function2()
{
emit sig();
}
I am invoking function1() multiple times.
function2() is also triggered multiple times
What I want is, whenever sig() is emitted slt() should be called, but what's happening is, first time when sig() is emitted slt() is being called number of times function1() is invoked.
Next time when sig() is invoked slt() is not called.
It would be a great help, if somebody can help me achieve this.....
You should only call connect once. Move your code that calls connect to a different function that is only called once.
So I´m not sure you understand what you are doing or what you want. So I´ll explain what is happening and then we can rethink what you want. Qt is working as expected. You said you want the slot to be called whenever the signal is emitted. That is exactly what your code is doing.
Now the question is ... are you aware that you create a new instance of your class2 each time function1 is called? Are you sure you didn´t just want a single instance of class2? Because that would then behave more in the way that you want it to.
class2 *obj = 0;
void class1::function1()
{
if(!obj)
{
obj = new class2();
connect(this, SIGNAL(sig()), obj, SLOT(slt()));
}
}
void class2::function2()
{
emit sig();
}
Since I have no idea where you create an object of class1, I just gave you something based on what you gave us. This should behave in the way you want it to. If that confuses you, I would suggest you should google some tutorials on learning C++, or object oriented programming (OOP) for that matter. Unfortunately I cannot recommend you any books/tutorials or else I would.
I hope this helps you.
The original code is to big to be posted here. Basically, I'm doing this:
class MySuperClass
{
QThread thread;
MyClass myObject;
MySuperClass()
{
connect( this, &MySuperClass::onKill, &myObject, &MyClass::stop );
connect( &thread, &QThread::started, &myObject, &MyClass::loop );
connect(&myObject, &MyClass::finished, &thread, &QThread::quit );
myObject.moveToThread( &thread );
qRegisterMetaType<uint16_t>("uint32_t");
connect( this, &MySuperClass::changed, &myObject, &MyClass::onChange );
}
void do()
{
emit changed(0);
}
}
'onKill - stop' signal/slot have no parameters and work fine. No problem here.
Problem is 'changed - onChange' pair. They have one parameter of type uint32_t (which I have registered).
When I call method do of MySuperClass from the main thread the signal is emitted, the slot onChange is called but it's parameter is not 0!
It's some big number like 3043426304.
The funny part is: if I change connection type to DirectConnection - parameter is zero; if I change connection type to QueuedConnection - parameter is zero too! How can this be? Isn't AutoConnection either Queued or Direct?
I'm very puzzled by this. First of all: how stack allocated integer type parameter may be corrupted like that? I'd understand if it was something heap-allocated or used in multiple threads.
My second question is: how should I do this connection properly? Does the order of connect and moveToThread matter?
Question 1 is answered by Chris. For question 2 (I did not see that the first time around)...
This is how to setup an object running in a seperate thread:
// Create the myObject object in its own thread
QThread* myThread= new QThread(); // you can assign `this` as parent if you want...
MyObject* myObject= new MyObject(0); // Assign no parent here (for QObject)
QObject::connect(myThread, &QThread::started, myObject, &MyObject::run, Qt::QueuedConnection);
myObject->moveToThread(myThread);
myThread->start();
You mostly have it correct. I think you are missing the "myThread->start()" function to kick the thread off. In your object creation its important to know that any dynamic allocations will be created in the parent thread space since the constructor runs before you move it to the thread. So its best to instantiate any objects you need inside the run() slot.
Any interaction with object once you start the thread should be via slots/signals.
Once you start the thread, it will emit started and your run() slot will be called.
The order of connect and moveToThread does not matter so long as you do all this before you call myThread->start()
Note
This is good for starting up a thread. There are some rules that may help you terminating the thread cleanly as well... but that's probably going off-topic
I am currently wondering how to reasonably use the QObject::destroyed(QObject*) signal.
An observation
I noticed that QWidget-derived objects are treated slightly different. Consider the following small self-contained and compiling example:
/* sscce.pro:
QT += core gui widgets
CONFIG += c++11
TARGET = sscce
TEMPLATE = app
SOURCES += main.cpp
*/
#include <QApplication>
#include <QPushButton>
#include <QTimer>
#include <QtDebug>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::destroyed,
[=](QObject *o) { qDebug() << o; });
delete button;
QTimer *timer = new QTimer;
QObject::connect(timer, &QTimer::destroyed,
[=](QObject *o) { qDebug() << o; });
delete timer;
return app.exec();
}
This is its output:
QWidget(0x1e9e1e0)
QObject(0x1e5c530)
So presumably, the signal is emitted from QObject's d-tor, so only the QObject base remains when the slot is called for the QTimer. However, QWidget's d-tor seems to intercept as it still identifies itself as a QWidget from the slot.
And the problem
Let's assume we have a timer pool that organizes a couple of timers in a QList<QTimer *>:
struct Pool {
QTimer *getTimer() {
return timers.at(/* some clever logic here */);
}
QList<QTimer *> timers;
};
Now an incautious user might delete the timer that was borrowed to him/her. Well, we can react, and simply remove that timer from the list. A slot will do the trick:
Pool::Pool() {
/* for each timer created */
connect(theTimer, SIGNAL(destroyed(QObject*),
this, SLOT(timerDestroyed(QObject*));
}
void Pool::timerDeleted(QObject *object) {
QTimer *theTimer = /* hrm. */
timers.removeOne(theTimer);
}
But what now? Hrm. When the slot is called, the QTimer already is in destruction and partially destroyed - only its QObject base remains. So I objously cannot qobject_cast<QTimer *>(object).
To resolve this issue, I could think of the following tricks:
Store QObjects in the list. Then I'd have to downcast every time I use an item from the list. This could be done using static_cast, though, as I know there will only be QTimers in the list, so no need for dynamic_cast or qobject_cast.
Insteat of removeOne traverse the list using an iterator and then compare each QTimer item directly to the QObject. Then use QList::erase or such.
static_cast or even reinterpret_cast the QObject to a Qtimer nonetheless.
What should I do?
If you're looking for tricks, you could simply use the base QObject objectName and remove the destroyed timer based on that.
It seems clear that your problem is one of object ownership; in particular, how to convey who is responsible for destroying an object. If your Pool object owns the QTimer objects (and thus the user should not delete them), make it clear through the interface, for example returning a QTimer& instead of a QTimer* from your getTimer method. I'm not really well versed in Qt, but if you actually wanted to transmit ownership of the object returned from a method and thus make the user responsible of its deletion, you'd likely return a std::unique_ptr<QTimer>.
Just do a direct cast:
void Pool::timerDeleted(QObject *object) {
QTimer *theTimer = (QTimer*)object; //qobject_cast doesn't work here
//we are sure that only a timer can be a sender
timers.removeOne(theTimer);
}
You could base your list on QPointer instead of raw pointers. I.e. write
QList<QPointer<QTimer>> timers;
Now when one of the timers in the list goes away, the corresponding entry in the list will automagically be cleared. It will not be removed, though! But when you access the timer via your getTimer() method, an entry whose timer has been deleted will now return a nullptr (and not a dangling pointer).
And yes, QWidget emits destroyed() in its own destructor. This is why you see a real QWidget in that case. Everybody else uses QObject's implementation.
The other way around is safe. Cast QTimer * to QObject * instead:
void Pool::timerDeleted(QObject *object) {
const auto it = std::find_if(timers.begin(), timers.end(), [object](QTimer *timer) {
return static_cast<QObject *>(timer) == object;
});
Q_ASSERT(it != timers.end());
timers.erase(it);
}
Or use erase_if(QList &list, Predicate pred) introduced in Qt 6.1.
I recently joined a new project, which is full with idiom like: ,
void foo()
{
Widget* temp = new Widget;
connect(temp, &Widget::signalTriggerred,[this, temp ]()
{
do cool staff...
}
}
As you can see no delete nothing, I am afraid even user class "Widget" is inherited QObject, this is still a leak. Does QT do something fancy to prevent leek in case above?
What I am planning to do:
void foo
{
std::shared_ptr<Widget > temp( new Widget () );
connect(temp.get(), &Widget::signalTriggerred,[this, temp] ()
{
do even cooler things...
}
}
Is there a problem with my apporach? (For example I didn't want to use .get() but compiler errors forced me to use it).
Edit : Since there is no parent in my case it is different. Duplicated question seek answer for parent-child cases. I am already aware in that case there will be no leek. In my question I am asking about creating a local QObject based object. And connecting it.
Not quite sure what you're wanting from the question, but if you need to delete the widget and it is derived from QObject, you can delete it in the lambda expression, assuming it's not going to be used after this scope:
void foo()
{
Widget* temp = new Widget;
connect(temp, &Widget::signalTriggerred,[this, temp ]()
{
temp->deleteLater();
}
}
This very much depends on the context.
If the temp widget is actually a visible top-level widget (no parent QWidget), then the widget needs to be kept alive until the user closes it. You can achieve it getting deleted automatically when being closed using:
widget->setAttribute(Qt::WA_DeleteOnClose);
If the temp widget however is inserted into the layout of some parent widget, Qt will automatically insert it into the QObject ownership tree and temp will have the same lifetime as its parent, see QObject::setParent().
The shared_ptr by itself saves nothing because it does not answer the question of intended lifetime of widget.