Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit()
-
I encountered a strange problem. Here is code:
In main.qml there is just a button, which emits signal buttonClicked() when it was pressed:int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); Foo fooObject; QObject* rootObject = engine.rootObjects().first(); QObject::connect(rootObject, SIGNAL(buttonClicked()), &fooObject, SLOT(start_process())); return app.exec(); }
In Foo header:
QProcess *process;
And here is Foo source:
void Foo::start_process() { process = new QProcess; QObject::connect(process, SIGNAL(readyRead()), this, SLOT(wait_test())); QObject::connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater())); process->start("uname -a"); //just for exaple qDebug() << "Process started"; } void Foo::wait_test() { QEventLoop localLoop; QTimer::singleShot(5000, &localLoop, SLOT(quit())); localLoop.exec(); qDebug() << "Time is up"; }
After wait_test() completed SIGSEGV occurs in QQuiApplication::exec() .
I am sure that it is my mistake, but i don't know where...
I'm using Qt 5.7 under Ubuntu with g++ compiler -
This is likely the reason for the crash:
QEventLoop localLoop; QTimer::singleShot(5000, &localLoop, SLOT(quit()));
Class 'localLoop' is not on the heap so it would be destroyed when this member function wait_test() returns. After 5 seconds the timer tries to access this class which no longer exists and you have a segfault.
I am not entirely sure what your goal is with this. If you want handle a case for something that doesn't respond (therefore finished() is never called) maybe have the timer call finished() with an -1 for an integer value (something you can use to detect an error).
-
I was wondering that too
but wont
localLoop.exec(); // block
so it wont run out of scope? -
I encountered a strange problem. Here is code:
In main.qml there is just a button, which emits signal buttonClicked() when it was pressed:int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); Foo fooObject; QObject* rootObject = engine.rootObjects().first(); QObject::connect(rootObject, SIGNAL(buttonClicked()), &fooObject, SLOT(start_process())); return app.exec(); }
In Foo header:
QProcess *process;
And here is Foo source:
void Foo::start_process() { process = new QProcess; QObject::connect(process, SIGNAL(readyRead()), this, SLOT(wait_test())); QObject::connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater())); process->start("uname -a"); //just for exaple qDebug() << "Process started"; } void Foo::wait_test() { QEventLoop localLoop; QTimer::singleShot(5000, &localLoop, SLOT(quit())); localLoop.exec(); qDebug() << "Time is up"; }
After wait_test() completed SIGSEGV occurs in QQuiApplication::exec() .
I am sure that it is my mistake, but i don't know where...
I'm using Qt 5.7 under Ubuntu with g++ compiler@MatrixSan What's the backtrace from the crash?
-
This is likely the reason for the crash:
QEventLoop localLoop; QTimer::singleShot(5000, &localLoop, SLOT(quit()));
Class 'localLoop' is not on the heap so it would be destroyed when this member function wait_test() returns. After 5 seconds the timer tries to access this class which no longer exists and you have a segfault.
I am not entirely sure what your goal is with this. If you want handle a case for something that doesn't respond (therefore finished() is never called) maybe have the timer call finished() with an -1 for an integer value (something you can use to detect an error).
This program runs in QEventLoop::exec() 5 seconds and after that, crash in QGuiApplication::exec(). It crashes frequently but not always. And I noticed the dependence of the frequency of the program falls on the delay time. The more delay the more likely program crashes
-
This program runs in QEventLoop::exec() 5 seconds and after that, crash in QGuiApplication::exec(). It crashes frequently but not always. And I noticed the dependence of the frequency of the program falls on the delay time. The more delay the more likely program crashes
@MatrixSan Throw it in gdb and give us a backtrace it will probably be pretty obvious from that what the issue is.
-
@MatrixSan Throw it in gdb and give us a backtrace it will probably be pretty obvious from that what the issue is.
@ambershark Is it it?
Thread 1 "QtBug" received signal SIGSEGV, Segmentation fault.
0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
(gdb) bt full
#0 0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#1 0x00007ffff6c25d11 in QIODevice::channelReadyRead(int) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#2 0x00007ffff6ad1506 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#3 0x00007ffff6ad18b0 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#4 0x00007ffff6bb4056 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#5 0x00007ffff6c29bfe in QSocketNotifier::activated(int, QSocketNotifier::QPrivateSignal) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#6 0x00007ffff6bc0f2b in QSocketNotifier::event(QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#7 0x00007ffff6b8c98a in QCoreApplication::notify(QObject*, QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#8 0x00007ffff6b8cae0 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
() from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#9 0x00007ffff6bda53e in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#10 0x00007ffff27a11a7 in g_main_context_dispatch ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#11 0x00007ffff27a1400 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#12 0x00007ffff27a14ac in g_main_context_iteration ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#13 0x00007ffff6bda05c in QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#14 0x00007ffff6b8adca in QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#15 0x00007ffff6b92bad in QCoreApplication::exec() ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#16 0x0000000000401e5f in main (argc=1, argv=0x7fffffffde58)
at ../QtBug/main.cpp:16
app = <incomplete type>
engine = <incomplete type>
fooObject = {<QObject> = {<No data fields>},
static staticMetaObject = {d = {
superdata = 0x7ffff70251c0 QObject::staticMetaObject,
stringdata = 0x4033e0 <qt_meta_stringdata_Foo>,
data = 0x403460 <qt_meta_data_Foo>,
static_metacall = 0x402c7a <Foo::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}},
process = 0x812fc0}
rootObject = 0x6b44a0
(gdb) -
@ambershark Is it it?
Thread 1 "QtBug" received signal SIGSEGV, Segmentation fault.
0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
(gdb) bt full
#0 0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#1 0x00007ffff6c25d11 in QIODevice::channelReadyRead(int) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#2 0x00007ffff6ad1506 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#3 0x00007ffff6ad18b0 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#4 0x00007ffff6bb4056 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#5 0x00007ffff6c29bfe in QSocketNotifier::activated(int, QSocketNotifier::QPrivateSignal) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#6 0x00007ffff6bc0f2b in QSocketNotifier::event(QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#7 0x00007ffff6b8c98a in QCoreApplication::notify(QObject*, QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#8 0x00007ffff6b8cae0 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
() from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#9 0x00007ffff6bda53e in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#10 0x00007ffff27a11a7 in g_main_context_dispatch ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#11 0x00007ffff27a1400 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#12 0x00007ffff27a14ac in g_main_context_iteration ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#13 0x00007ffff6bda05c in QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#14 0x00007ffff6b8adca in QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#15 0x00007ffff6b92bad in QCoreApplication::exec() ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#16 0x0000000000401e5f in main (argc=1, argv=0x7fffffffde58)
at ../QtBug/main.cpp:16
app = <incomplete type>
engine = <incomplete type>
fooObject = {<QObject> = {<No data fields>},
static staticMetaObject = {d = {
superdata = 0x7ffff70251c0 QObject::staticMetaObject,
stringdata = 0x4033e0 <qt_meta_stringdata_Foo>,
data = 0x403460 <qt_meta_data_Foo>,
static_metacall = 0x402c7a <Foo::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}},
process = 0x812fc0}
rootObject = 0x6b44a0
(gdb)@MatrixSan Thanks, yea from that it looks like QEventLoop is out of scope and cleaned up. Try allocating it on the heap (without worrying bout clean up for now) just to test and see if that goes away. It should.
Basically that backtrace is saying it is trying to call activate on a pointer that is invalid (dangling). So the memory was already cleaned up. This is why you rarely see Qt use
connect
on anything on the stack. It is almost guaranteed to crash at some point.Edit: Here is the code that should work:
void Foo::wait_test() { QEventLoop *localLoop = new QEventLoop(); QTimer::singleShot(5000, localLoop, SLOT(quit())); localLoop->exec(); qDebug() << "Time is up"; localLoop->deleteLater(); }
-
@MatrixSan Thanks, yea from that it looks like QEventLoop is out of scope and cleaned up. Try allocating it on the heap (without worrying bout clean up for now) just to test and see if that goes away. It should.
Basically that backtrace is saying it is trying to call activate on a pointer that is invalid (dangling). So the memory was already cleaned up. This is why you rarely see Qt use
connect
on anything on the stack. It is almost guaranteed to crash at some point.Edit: Here is the code that should work:
void Foo::wait_test() { QEventLoop *localLoop = new QEventLoop(); QTimer::singleShot(5000, localLoop, SLOT(quit())); localLoop->exec(); qDebug() << "Time is up"; localLoop->deleteLater(); }
@ambershark thank you for your reply, but program crashes anyway...
Thread 1 "QtBug" received signal SIGSEGV, Segmentation fault.
0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
(gdb) bt full
#0 0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#1 0x00007ffff6c25d11 in QIODevice::channelReadyRead(int) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#2 0x00007ffff6ad1506 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#3 0x00007ffff6ad18b0 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#4 0x00007ffff6bb4056 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#5 0x00007ffff6c29bfe in QSocketNotifier::activated(int, QSocketNotifier::QPrivateSignal) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#6 0x00007ffff6bc0f2b in QSocketNotifier::event(QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#7 0x00007ffff6b8c98a in QCoreApplication::notify(QObject*, QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#8 0x00007ffff6b8cae0 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
() from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#9 0x00007ffff6bda53e in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#10 0x00007ffff27a11a7 in g_main_context_dispatch ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#11 0x00007ffff27a1400 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#12 0x00007ffff27a14ac in g_main_context_iteration ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#13 0x00007ffff6bda047 in QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#14 0x00007ffff6b8adca in QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#15 0x00007ffff6b92bad in QCoreApplication::exec() ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#16 0x0000000000401e5f in main (argc=1, argv=0x7fffffffde58)
at ../QtBug/main.cpp:16
app = <incomplete type>
engine = <incomplete type>
fooObject = {<QObject> = {<No data fields>},
static staticMetaObject = {d = {
superdata = 0x7ffff70251c0 QObject::staticMetaObject,
stringdata = 0x4033e0 <qt_meta_stringdata_Foo>,
data = 0x403460 <qt_meta_data_Foo>,
static_metacall = 0x402c90 <Foo::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}},
process = 0x94ab00}
rootObject = 0x6b4530 -
@ambershark thank you for your reply, but program crashes anyway...
Thread 1 "QtBug" received signal SIGSEGV, Segmentation fault.
0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
(gdb) bt full
#0 0x00007ffff6bb3d56 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#1 0x00007ffff6c25d11 in QIODevice::channelReadyRead(int) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#2 0x00007ffff6ad1506 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#3 0x00007ffff6ad18b0 in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#4 0x00007ffff6bb4056 in QMetaObject::activate(QObject*, int, int, void**) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#5 0x00007ffff6c29bfe in QSocketNotifier::activated(int, QSocketNotifier::QPrivateSignal) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#6 0x00007ffff6bc0f2b in QSocketNotifier::event(QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#7 0x00007ffff6b8c98a in QCoreApplication::notify(QObject*, QEvent*) ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#8 0x00007ffff6b8cae0 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
() from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#9 0x00007ffff6bda53e in ?? ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#10 0x00007ffff27a11a7 in g_main_context_dispatch ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#11 0x00007ffff27a1400 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#12 0x00007ffff27a14ac in g_main_context_iteration ()
from /lib/x86_64-linux-gnu/libglib-2.0.so.0
No symbol table info available.
#13 0x00007ffff6bda047 in QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#14 0x00007ffff6b8adca in QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) () from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
No symbol table info available.
#15 0x00007ffff6b92bad in QCoreApplication::exec() ()
from /home/san/Qt/5.7/gcc_64/lib/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
No symbol table info available.
#16 0x0000000000401e5f in main (argc=1, argv=0x7fffffffde58)
at ../QtBug/main.cpp:16
app = <incomplete type>
engine = <incomplete type>
fooObject = {<QObject> = {<No data fields>},
static staticMetaObject = {d = {
superdata = 0x7ffff70251c0 QObject::staticMetaObject,
stringdata = 0x4033e0 <qt_meta_stringdata_Foo>,
data = 0x403460 <qt_meta_data_Foo>,
static_metacall = 0x402c90 <Foo::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}},
process = 0x94ab00}
rootObject = 0x6b4530@MatrixSan Oops I didn't look far enough in the bt.. So the problem here is actually that readyRead is called after the QProcess has been cleaned up. Just to confirm try commenting out your line where you connect
finish
todeleteLater
.If it still crashes I'll look in more detail however I'm 95% sure that is the crash. For reals this time. ;)
Edit: Oh and if it really is the crash as I suspect then to fix it you can deal with all the stuff pending the read on the socket after the process exists and then delete your QProcess, or you can disconnect the readyRead signal before deleting QProcess. Or you could even turn off the IO from the QProcess if you don't really need it... or don't connect readyRead in the first place if you don't need it. Any of those should fix it permanently without disabling your deleteLater.
-
@MatrixSan Oops I didn't look far enough in the bt.. So the problem here is actually that readyRead is called after the QProcess has been cleaned up. Just to confirm try commenting out your line where you connect
finish
todeleteLater
.If it still crashes I'll look in more detail however I'm 95% sure that is the crash. For reals this time. ;)
Edit: Oh and if it really is the crash as I suspect then to fix it you can deal with all the stuff pending the read on the socket after the process exists and then delete your QProcess, or you can disconnect the readyRead signal before deleting QProcess. Or you could even turn off the IO from the QProcess if you don't really need it... or don't connect readyRead in the first place if you don't need it. Any of those should fix it permanently without disabling your deleteLater.
@ambershark yeah that works =) thank you very much! But I still do not understand why the program falls only when I'm using QEventLoop ..
-
@ambershark yeah that works =) thank you very much! But I still do not understand why the program falls only when I'm using QEventLoop ..
@MatrixSan because readyRead has that event loop that doesn't quit for 5 seconds. So the QProcess is deleted before the previous readyRead exited. So the next readyRead tries to be called and the process is gone therefore segfault. :) You could simulate that same behavior and crash with a simple
sleep
. -
@MatrixSan because readyRead has that event loop that doesn't quit for 5 seconds. So the QProcess is deleted before the previous readyRead exited. So the next readyRead tries to be called and the process is gone therefore segfault. :) You could simulate that same behavior and crash with a simple
sleep
.@ambershark Now everything is clear. Thank you very much for a detailed description :)
-
@MatrixSan because readyRead has that event loop that doesn't quit for 5 seconds. So the QProcess is deleted before the previous readyRead exited. So the next readyRead tries to be called and the process is gone therefore segfault. :) You could simulate that same behavior and crash with a simple
sleep
.@ambershark said in Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit():
You could simulate that same behavior and crash with a simple sleep.
You can't because
sleep
will block event processing.@MatrixSan
As already mentioned using local event loops is a somewhat dubious decision. I suggest you add a timeout flag and set it in the handler of the timer signal, if you need to know when an operation has timed out. The problem is that the deferred deletion event is processed in the main event loop while you're still waiting forlocalLoop
. -
@ambershark said in Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit():
You could simulate that same behavior and crash with a simple sleep.
You can't because
sleep
will block event processing.@MatrixSan
As already mentioned using local event loops is a somewhat dubious decision. I suggest you add a timeout flag and set it in the handler of the timer signal, if you need to know when an operation has timed out. The problem is that the deferred deletion event is processed in the main event loop while you're still waiting forlocalLoop
.@kshegunov I'm using local event loop because in project where I ran into this problem with "segfault" sometimes there is need to show MessageDialog with warning message and i want to block code execution until user will press "ok" button or close the window and event loop just waits for signal from it. Like this:
mainViewEngine->load(QUrl("qrc:/src/core/interfaces/WarningMessage.qml")); QEventLoop localLoop; QObject::connect(moduleObject, SIGNAL(closeSignal()), &localLoop, SLOT(quit())); localLoop.exec();
Is it right way?
-
@kshegunov I'm using local event loop because in project where I ran into this problem with "segfault" sometimes there is need to show MessageDialog with warning message and i want to block code execution until user will press "ok" button or close the window and event loop just waits for signal from it. Like this:
mainViewEngine->load(QUrl("qrc:/src/core/interfaces/WarningMessage.qml")); QEventLoop localLoop; QObject::connect(moduleObject, SIGNAL(closeSignal()), &localLoop, SLOT(quit())); localLoop.exec();
Is it right way?
@MatrixSan said in Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit():
I'm using local event loop because in project where I ran into this problem with "segfault" sometimes there is need to show warning message and i want to block code execution until user will press "ok" button or close the window and event loop just waits for signal from it.
Then you need to call the
deleteLater
from the slot where you handle the timeout. Otherwise your code would be equivalent to callingdelete this
before you've returned from the slot, which is a bad, bad, bad idea.The simplest way is to make the process a stack variable and leave C++ to clean it up for you:class Foo : public QObject { Q_OBJECT private: QProcess process; public: void Foo::start_process() { // process = new QProcess; <- No need. QObject::connect(&process, SIGNAL(readyRead()), this, SLOT(wait_test())); process.start("uname -a"); //just for exaple qDebug() << "Process started"; } void Foo::wait_test() { QEventLoop localLoop; QTimer::singleShot(5000, &localLoop, SLOT(quit())); localLoop.exec(); qDebug() << "Time is up"; } }
-
@MatrixSan said in Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit():
I'm using local event loop because in project where I ran into this problem with "segfault" sometimes there is need to show warning message and i want to block code execution until user will press "ok" button or close the window and event loop just waits for signal from it.
Then you need to call the
deleteLater
from the slot where you handle the timeout. Otherwise your code would be equivalent to callingdelete this
before you've returned from the slot, which is a bad, bad, bad idea.The simplest way is to make the process a stack variable and leave C++ to clean it up for you:class Foo : public QObject { Q_OBJECT private: QProcess process; public: void Foo::start_process() { // process = new QProcess; <- No need. QObject::connect(&process, SIGNAL(readyRead()), this, SLOT(wait_test())); process.start("uname -a"); //just for exaple qDebug() << "Process started"; } void Foo::wait_test() { QEventLoop localLoop; QTimer::singleShot(5000, &localLoop, SLOT(quit())); localLoop.exec(); qDebug() << "Time is up"; } }
@kshegunov Thank you! Now all works fine.
-
@kshegunov I'm using local event loop because in project where I ran into this problem with "segfault" sometimes there is need to show MessageDialog with warning message and i want to block code execution until user will press "ok" button or close the window and event loop just waits for signal from it. Like this:
mainViewEngine->load(QUrl("qrc:/src/core/interfaces/WarningMessage.qml")); QEventLoop localLoop; QObject::connect(moduleObject, SIGNAL(closeSignal()), &localLoop, SLOT(quit())); localLoop.exec();
Is it right way?
@MatrixSan said in Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit():
@kshegunov I'm using local event loop because in project where I ran into this problem with "segfault" sometimes there is need to show MessageDialog with warning message and i want to block code execution until user will press "ok" button or close the window and event loop just waits for signal from it. Like this:
mainViewEngine->load(QUrl("qrc:/src/core/interfaces/WarningMessage.qml")); QEventLoop localLoop; QObject::connect(moduleObject, SIGNAL(closeSignal()), &localLoop, SLOT(quit())); localLoop.exec();
Is it right way?
But you should have a main event loop and you don't really need the local one since you have events to deal with the rest of what is going on. You just connect signals/slots for what you need to handle and your main event loop can deal with it. I agree with @kshegunov and wouldn't use local event loops on my main event loop thread without good reason.
Also the reason you are waiting is not a good one. Especially since you put an arbitrary 5s timeout. What if the user doesn't click the ok before that hits?
@kshegunov You are of course right that the
sleep
would block. I meant it more to illustrate the point not to actually put it in practice. The point being that the 5 second timer was causing a sleep like situation meaning the QProcess was cleaned up before the signal could get sent to it. -
@MatrixSan said in Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit():
@kshegunov I'm using local event loop because in project where I ran into this problem with "segfault" sometimes there is need to show MessageDialog with warning message and i want to block code execution until user will press "ok" button or close the window and event loop just waits for signal from it. Like this:
mainViewEngine->load(QUrl("qrc:/src/core/interfaces/WarningMessage.qml")); QEventLoop localLoop; QObject::connect(moduleObject, SIGNAL(closeSignal()), &localLoop, SLOT(quit())); localLoop.exec();
Is it right way?
But you should have a main event loop and you don't really need the local one since you have events to deal with the rest of what is going on. You just connect signals/slots for what you need to handle and your main event loop can deal with it. I agree with @kshegunov and wouldn't use local event loops on my main event loop thread without good reason.
Also the reason you are waiting is not a good one. Especially since you put an arbitrary 5s timeout. What if the user doesn't click the ok before that hits?
@kshegunov You are of course right that the
sleep
would block. I meant it more to illustrate the point not to actually put it in practice. The point being that the 5 second timer was causing a sleep like situation meaning the QProcess was cleaned up before the signal could get sent to it.@ambershark said in Segmentation fault in QQuiApplication::exec() after invoking QEventLoop::quit():
The point being that the 5 second timer was causing a sleep like situation meaning the QProcess was cleaned up before the signal could get sent to it.
No. I think you misunderstood.
deleteLater
will remove all pending events for a given object, however here it goes like this:- The signal is emitted and the slot is entered
- The local event loop is opened
- The local event loop spins the global event loop too(!) - that's the subtle point against using local event loops
- The deferred delete event is processed and
this
(the object whose slot we are currently in) is deleted. (bad) - The local event loop quits and we continue on to return from the slot
- SIGSEGV - we deleted the current object while we were in the slot
You can't reproduce that sequence of events with a sleep, or any other method that doesn't spin the event loop.
Kind regards.