antred
antred

Reputation: 3884

QApplication::exec() refuses to return (in console program)

I have a Qt C++ program that, although it isn't actually using a GUI (with the exception of a few message box popups) makes use of the QApplication::exec() method (necessary so the event loop is run and can service the whole signal/slot business). I'm also calling QApplication::setQuitOnLastWindowClosed( false ) because otherwise the program would end immediately when the user dismisses one of the message box popups. I don't think this should have any influence on the behavior I'm observing, but I'm mentioning it anyway, just in case.

At some point, of course, the program should end, and I have added a call to QApplication::exit() to cause Qt to fall out of its event loop and thus return from the QApplication::exec() call. According to the Qt documention on the QApplication::exec() method, this is precisely what should happen.

int QApplication::exec()

Enters the main event loop and waits until exit() is called, then returns the value that was set to exit() (which is 0 if exit() is called via quit()).

However, in my program it's just not happening. I've traced the program flow in a debugger and I know for sure that QApplication::exit() is called, but still QApplication::exec() doesn't seem to want to return. :(

I'm using Qt 5.4.1 with MinGW 3.11 (the GCC compiler identifies itself as version 4.9.1). My computer is running Windows 7 Enterprise (64 bit), Service Pack 1. Does anyone know what I might be doing wrong?

EDIT: Kuba Ober mentioned in his comment that QApplication::exec() is probably not returning because my code is blocking somewhere. I'd like to post this screenshot of the main thread's call stack to prove that the main thread is stuck deep inside the guts of Qt at this point and that my own code is not in fact in control.

Main thread call stack

SOLUTION: Ok, Rudolfs Bundulis' answer led me to the root of the problem. I had a little message box in my program that pops up and asks the user to perform a certain action (in this case, to switch on an external device that communicates with my program). For the program flow to continue, it is not necessary to dismiss this popup; it is sufficient to simply turn on the external device, and so I forgot to dismiss the message box and just left it alone. Later, when QApplication::exit() is called, Qt seems to destroy the message box (or at least make it invisible) so it can no longer be dismissed, and as Rudolfs Bundulis has pointed out, an open message box is enough to keep QApplication::exec() from returning.

Upvotes: 2

Views: 3393

Answers (1)

Rudolfs Bundulis
Rudolfs Bundulis

Reputation: 11954

The mechanism you described should work. Here is a small snippet with two ways of terminating a QApplication just the way you inteded - either via a direct the QApplication::quit() slot or the QApplication::exit() call. Both seem to work.

QApplicationTerminator.h:

#pragma once

#include <QObject>
#include <QDebug>
#include <QApplication>

class QApplicationTerminator : public QObject
{
    Q_OBJECT

public slots:
    void quit()
    {
        qDebug() << "terminating QApplication\n";
        QApplication::exit(0);
    }
};

main.cpp:

#include "qapplicationterminator.h"

#include <QApplication>
#include <QTimer>
#include <QDebug>
#include <QThread>

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    QApplicationTerminator terminator;
    QTimer::singleShot(3000, &application, SLOT(quit()));
    //QTimer::singleShot(3000, &terminator, SLOT(quit()));
    application.setQuitOnLastWindowClosed(false);
    auto result = application.exec();
    qDebug() << "event loop exited\n";
    return result;
}

I'll have to agree with @KubaOber that most likely you are either blocking somewhere.

Since you mentioned dialogs - dialogs run their own event loop, if any of the event loops of your dialogs are still running (this however should not happen if they are properly used) the main event loop simply does not get back in control and cannot exit.

Upvotes: 2

Related Questions