5

I have a console-based QCoreApplication which has timers and does socket communication and also uses locked mutex.

When I close the application manually, it gives error saying some mutex is locked and it is timed out. Is there any way I can do clean up in a console application when user closes it?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Suresh
  • 9,495
  • 14
  • 49
  • 63

3 Answers3

18

Cleanup should be handled by destructors and child-parent relationship.

Make your master object (the one in the main) a child of QApplication so it is destructed with all its childs before QApplication is.

Are you sure you killed all your threads? If it is a thread with an eventloop be sure to call QThread::quit() to exit the eventloop before you call QThread::wait()

You can also use the void QApplication::qAddPostRoutine ( QtCleanUpFunction ptr ) to do some special cleanup.

For debugging those messages you can use QtMsgHandler qInstallMsgHandler ( QtMsgHandler h ) and write your own message handler to capture those warnings. If you can simulate the problem you can set a breakpoint on the message and see on the stack where the message is coming from.

void debugMessageHandler( QtMsgType type, const char *msg ){
    if(QString(msg).contains( "The message you can see in the console" )){
        int breakPointOnThisLine(0);    
    }

    switch ( type ) {
        case QtDebugMsg:
            fprintf( stderr, "Debug: %s\n", msg );
            break;
        case QtWarningMsg:
            fprintf( stderr, "Warning: %s\n", msg );
            break;
        case QtFatalMsg:
            fprintf( stderr, "Fatal: %s\n", msg );
            abort();
    }
}

In order to clean up with destructor and child-parent relation ship you can catch the console close signal and call QCoreApplication::exit() to the application instance.

#include <csignal>
#include <QtCore/QCoreApplication>
using namespace std;

struct CleanExit{
    CleanExit() {
        signal(SIGINT, &CleanExit::exitQt);
        signal(SIGTERM, &CleanExit::exitQt);
        signal(SIGBREAK, &CleanExit::exitQt) ;
    }

    static void exitQt(int sig) {
        QCoreApplication::exit(0);
    }
};


int main(int argc, char *argv[])
{
    CleanExit cleanExit;
    QCoreApplication a(argc, argv);
    return a.exec();
}
TimW
  • 8,351
  • 1
  • 29
  • 33
  • almost complete. once you have called exit(0) you have to do your Qt specific cleanup code somewhere that is not in the signal handler exitQt(). so you have to tie your Qt cleanup code to the aboutToQuit() signal. the aboutToQuit signal is only emitted once the qApp->exit(0) is called. – Trevor Boyd Smith Sep 22 '11 at 18:31
  • 2
    c++11 makes it more easy: `signal(SIGTERM, [](int sig){ qApp->quit(); });` – ManuelSchneid3r Oct 12 '15 at 16:49
  • This is not fully working. I have made the cleanup-related object a child of QApplication. The destructor is properly called when the window is closed normally. But upon system shutdown/logout, the QApplication child destructor is never called. – galinette Jun 10 '16 at 19:37
  • Calling Qt functions from unix signals is not supported (Might hang, corrupt data etc). See http://doc.qt.io/qt-5/unix-signals.html . This code might leave the user unable to quit the program via ctrl-c. See also https://stackoverflow.com/a/37482031/4973666 – textshell Nov 16 '17 at 09:50
5

Turns out that closing command line application (checked on Win7 & VS2010) by pressing 'close' (red x button on title bar) passes the STATUS_CONTROL_C_EXIT signal to the application. All threads are aborted with this code.

The thread 'Main Thread' (0x980) has exited with code -1073741510 (0xc000013a).

The thread 'QThread' (0x2388) has exited with code -1073741510 (0xc000013a).

That means that there is no way to intercept this with the QCoreApplication::aboutToQuit() signal.

Take a look at winnt.h or ntstatus.h. That is the value assigned to the manifest constant STATUS_CONTROL_C_EXIT. The runtime is just choosing to end your program with the code to note the user's cancel operation.

Benoit Garret
  • 14,027
  • 4
  • 59
  • 64
1

you can connect to QCoreApplication::aboutToQuit signal and do the necessary clean up there.

Linville
  • 3,613
  • 1
  • 27
  • 41
Idan K
  • 20,443
  • 10
  • 63
  • 83
  • 2
    Hi Daniel, I tried this, but break point doesn't hit in the connected SLOT. documentation says aboutToQuit signal is emitted when quit on QCoreApplication is called. Does the closing of console application invoke quit()? Thanks, Suresh. – Suresh Jun 10 '09 at 13:46