QApplication 后的清理

Ded*_*eak 7 linux qt multithreading googletest qapplication

我正在将 Qt 桌面应用程序移植到 Linux(Ubuntu 19.10,64 位桌面,Qt 5.12.5,gcc 版本 9.2.1),并且在 QApplication 完成后我看到一些意外的线程保持活动状态。

这是最低限度的再现:

#include <QApplication>
#include <unistd.h>
int main(int argc, char * argv[]) {
    {
        QApplication app(argc, argv);
        sleep(1);
    }
    sleep(10);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我在不同的时间点调试应用程序,我会看到以下内容:

  • 在运行 QApplication 的构造函数之前,正如预期的那样,只有一个线程,即主线程,存在。
  • 运行 QApplication 的构造函数后,会创建 4 个额外的线程:
    • QXcbEventQueue
    • 主界面
    • 总线
    • QDBusConnection
  • QApplication 的析构函数运行后,QXcbEventQueue 线程消失。
  • 即使在 10 秒的第二次睡眠完成后,除了主线程之外,其他 3 个线程仍然活着:
    • 主界面
    • 总线
    • QDBusConnection

在 QApplication 完成后,我正在寻找一种方法来正确结束这些线程(并进行我目前可能不知道的其他清理工作)(当然,在实际应用程序中,我调用 app.exec() 并执行其他东西)并已被销毁。

这不是应用程序本身的问题,在这 3 个线程仍然活着的情况下到达 main 的末尾似乎没有问题。

该应用程序是使用 Google Test 进行全面测试的更大的库/其他应用程序套件的一部分,这些测试包括一些死亡测试,如果在运行了一些涉及运行 QApplication 的测试后执行,则会抱怨分叉应用程序有多个线程,并且卡住并且永远不会完成,大概是因为这个原因。

关于我如何能够摆脱这些线程并在 QApplication 之后执行完全清理的任何提示?

Man*_*lva 7

我正在寻找一种正确结束这些线程的方法

简答。

你不能

长答案。

那些在QApplication销毁后仍然保持活动状态的线程肯定是由创建的,QApplication但这些线程是使用分离模式创建的on查看更多信息。当任何线程以分离模式创建时on,它既不能加入也不能设置回可加入。

要验证以上检查代码。这是创建所有集成插件的地方。在此处添加断点并在调试期间(在 GDB 中)进入代码。或者您也可以将断点设置为 function pthread_attr_setdetachstate

现在来解决问题。

检查这个

两种死亡测试风格的原因与线程安全有关。由于存在线程时分叉的众所周知的问题,死亡测试应该在单线程上下文中运行

因此,google-test库开发人员非常了解您面临的问题,并且他们也有针对此类情况的解决方案。看这里

我相信这会对你有所帮助。