在关闭QCoreApplication之前清理

时间:2022-08-29 22:14:20

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

我有一个基于控制台的QCoreApplication,它有定时器和套接字通信,还使用锁定的互斥锁。

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?

当我手动关闭应用程序时,它会提示错误,说某些互斥锁被锁定并且超时。当用户关闭它时,我有什么方法可以在控制台应用程序中清理它?

3 个解决方案

#1


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.

使您的主对象(主要对象)成为QApplication的子对象,以便在QApplication之前对其所有子对象进行破坏。

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()

你确定你杀了你所有的线程吗?如果它是一个带有eventloop的线程,请确保在调用QThread :: wait()之前调用QThread :: quit()以退出eventloop

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

您还可以使用void QApplication :: qAddPostRoutine(QtCleanUpFunction ptr)进行一些特殊清理。

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.

要调试这些消息,您可以使用QtMsgHandler qInstallMsgHandler(QtMsgHandler h)并编写自己的消息处理程序来捕获这些警告。如果您可以模拟问题,可以在消息上设置断点,并在堆栈上查看消息的来源。

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.

为了清理析构函数和子父关系,您可以捕获控制台关闭信号并将QCoreApplication :: exit()调用到应用程序实例。

#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();
}

#2


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.

原来关闭命令行应用程序(在Win7和VS2010上检查)按“关闭”(标题栏上的红色x按钮)将STATUS_CONTROL_C_EXIT信号传递给应用程序。使用此代码中止所有线程。

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

线程'Main Thread'(0x980)已退出,代码为-1073741510(0xc000013a)。

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

线程'QThread'(0x2388)已退出,代码为-1073741510(0xc000013a)。

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

这意味着没有办法用QCoreApplication :: aboutToQuit()信号拦截它。

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.

看看winnt.h或ntstatus.h。这是分配给清单常量STATUS_CONTROL_C_EXIT的值。运行时只是选择使用代码结束程序以记录用户的取消操作。

#3


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

您可以连接到QCoreApplication :: aboutToQuit信号并在那里进行必要的清理。

#1


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.

使您的主对象(主要对象)成为QApplication的子对象,以便在QApplication之前对其所有子对象进行破坏。

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()

你确定你杀了你所有的线程吗?如果它是一个带有eventloop的线程,请确保在调用QThread :: wait()之前调用QThread :: quit()以退出eventloop

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

您还可以使用void QApplication :: qAddPostRoutine(QtCleanUpFunction ptr)进行一些特殊清理。

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.

要调试这些消息,您可以使用QtMsgHandler qInstallMsgHandler(QtMsgHandler h)并编写自己的消息处理程序来捕获这些警告。如果您可以模拟问题,可以在消息上设置断点,并在堆栈上查看消息的来源。

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.

为了清理析构函数和子父关系,您可以捕获控制台关闭信号并将QCoreApplication :: exit()调用到应用程序实例。

#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();
}

#2


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.

原来关闭命令行应用程序(在Win7和VS2010上检查)按“关闭”(标题栏上的红色x按钮)将STATUS_CONTROL_C_EXIT信号传递给应用程序。使用此代码中止所有线程。

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

线程'Main Thread'(0x980)已退出,代码为-1073741510(0xc000013a)。

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

线程'QThread'(0x2388)已退出,代码为-1073741510(0xc000013a)。

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

这意味着没有办法用QCoreApplication :: aboutToQuit()信号拦截它。

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.

看看winnt.h或ntstatus.h。这是分配给清单常量STATUS_CONTROL_C_EXIT的值。运行时只是选择使用代码结束程序以记录用户的取消操作。

#3


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

您可以连接到QCoreApplication :: aboutToQuit信号并在那里进行必要的清理。