Application events being processed after exit() call - bug or feature??
-
Hey all!
Im wondering why qt application event loop process some events after exit() call ?Consider such a simple demo app:
#include <QCoreApplication> #include <QDebug> #include <QTimer> void print(int code) { qDebug() << code; } void reproduceBug() { QTimer::singleShot(0, nullptr, [](){print(1);}); QTimer::singleShot(0, nullptr, [](){QCoreApplication::exit(0);}); QTimer::singleShot(0, nullptr, [](){print(2);}); QTimer::singleShot(0, nullptr, [](){print(3);}); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); reproduceBug(); return a.exec(); }
I would expect output to be
11:56:15: Starting ..\QtBugExitEventLoop.exe ... 1 11:56:15: ..\QtBugExitEventLoop.exe exited with code 0
But actual output is
11:56:15: Starting ..\QtBugExitEventLoop.exe ... 1 2 3 11:56:15: ..\QtBugExitEventLoop.exe exited with code 0
You can see that message loop events still being processed after call to exit() !
Looks like a bug, isn't it?.Documentation for qcoreapplication::exit says
After this function has been called, the application leaves the main event loop and returns from the call to exec().
So why it does not exit?
Looking in source code I see that
application::exec
runs message loop which have check for exit:int QEventLoop::exec(ProcessEventsFlags flags) { ... while (!d->exit.loadAcquire()) <----- check processEvents(flags | WaitForMoreEvents | EventLoopExec);
But the method
processEvents
itself leads toQCoreApplicationPrivate::sendPostedEvents
and always process whole bunch of events which are in list by the time of the call to it:void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type, QThreadData *data) { ... while (i < data->postEventList.size()) { // avoid live-lock if (i >= data->postEventList.insertionOffset) break; const QPostEvent &pe = data->postEventList.at(i); ++i; // and various checks but no one for exit called.. ... QCoreApplication::sendEvent(r, e); } ... }
Should I report a bug or this is somehow expected (by who?) behaviour?
-
@alexwtan QTimer::singleShot(0, ...) calls put all these 4 events into event loop. Next time the event loop runs it handles all events which are currently in the event loops. So, all 4 lambdas are executed and then the exit() tells event loop to terminate (in the while() condinion you posted). processEvents() processes all events as far as I know currently waiting in the event loop.
So, no bug, works as expected. -
@jsulm Thank you for the clarifications!.
I understand why current code works how it works. But sorry, I'm still don't understand why it is ok to process any application event after exit() call :)
What if I have 2 events in list: first is user click on close application (exit() called while processing) and 2nd is message that starts long calculation process in background? I shouldn't process 2nd and this information is obvious to qt since exit flag is raised to moment when it will start processing 2nd event.
Why I'm pushed to spawn redundant checks in user code instead of just do the work right in qt framework?