PDA

View Full Version : SIGSEGV after invoking QML method from c++ thread



MatrixSan
10th December 2016, 12:49
Hello! I'm trying to write GUI for some console applications and I'm stuck on strange problem...

In main function:

int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);

QQmlApplicationEngine engine(QUrl::fromLocalFile("test.qml"));

Foo fooObject(&engine);

QThread thread;
fooObject.moveToThread(&thread);

QObject::connect(&thread, SIGNAL(started()), &fooObject, SLOT(start_slot()));

thread.start();

return a.exec();
}
In Foo header file:

QProcess* testProcess;
Slot, invoked after thread started:

void Foo::start_slot()
{
testProcess = new QProcess;
connect(testProcess, SIGNAL(finished(int)), this, SLOT(finish_slot()));
testProcess->start("uname -a"); //just for example
}
After completion this slot SIGSEGV occurs:

void Foo::finish_slot()
{
delete (testProcess);
QObject* moduleObject = engineObject->rootObjects().first()->findChild<QObject*>("testModule");
QMetaObject::invokeMethod(moduleObject, "test");
}
But this works fine...

void Foo::finish_slot()
{
QObject* moduleObject = engineObject->rootObjects().first()->findChild<QObject*>("testModule");
QMetaObject::invokeMethod(moduleObject, "test");
delete (testProcess);
}

Is it bug or my mistake? Thanks!

anda_skoa
11th December 2016, 11:45
The finish_slot is called from a signal originating from the process and it is usually not a good idea to delete an object while its code is still being executed.

Best way to delete an object in a slot connected to one of its signals is to call QObject::deleteLater() on the signal sender instead of invoking the delete operator.

Some other observations:

1) why the thread?

2) consider exposing an object to QML instead of retrieving an object from there and invoking its methods: http://doc.qt.io/qt-5/qtqml-cppintegration-contextproperties.html#setting-an-object-as-a-context-property

Cheers,
_

MatrixSan
11th December 2016, 13:20
Thank you! Now with deleteLater() all works well!
I'm using thread, because in project where I ran into this problem with "segfault" there is need to work with data coming from processes and handle them so I thought it's good idea to use threads to prevent GUI freezing. Also there is need to append this data on TextArea on qml side and to block some interface elements during the processes running that is why I decided to invoke qml methods.

anda_skoa
12th December 2016, 10:49
I'm using thread, because in project where I ran into this problem with "segfault" there is need to work with data coming from processes and handle them so I thought it's good idea to use threads to prevent GUI freezing.

QProcess runs asynchronously.
Unless you need a lot of expensive processing on process data or finish, you are way better of not using threads.



Also there is need to append this data on TextArea on qml side and to block some interface elements during the processes running that is why I decided to invoke qml methods.

Both of which can be done way cleaner by letting QML code react to data and changes reported from C++.

Cheers,
_

MatrixSan
12th December 2016, 14:57
Thank you very much! I will try to change the architecture of my application.