Search code examples
linuxmultithreadingqtgoogletestqapplication

Cleaning up after QApplication


I'm porting a Qt desktop application to Linux (Ubuntu 19.10, 64bit desktop, Qt 5.12.5, gcc version 9.2.1), and am seeing some unexpected threads remaining alive after QApplication is finished.

Here's the minimum repro:

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

If I debug the application at various points in time, here's what I see:

  • Before the constructor of QApplication is run, just one thread, the main thread, exists, as expected.
  • After the constructor of QApplication is run, 4 additional threads get created:
    • QXcbEventQueue
    • gmain
    • gdbus
    • QDBusConnection
  • After the destructor of QApplication is run, the QXcbEventQueue thread goes away.
  • Even after the second sleep of 10 seconds is done, the 3 other threads, besides the main thead, remain alive:
    • gmain
    • gdbus
    • QDBusConnection

I'm looking for a way to properly end these threads (and do other clean up that I might not be aware of at the moment) after QApplication has finished (of course, in the real app I call app.exec() and do other things) and has been destroyed.

This is not an issue in the application itself, which does not seem to have a problem with reaching the end of main with those 3 threads still alive.

The application is part of a larger suite of libraries / other applications that are thoroughly tested using Google Test, and the tests include some Death Tests, which, if executed after having run some tests that involve running a QApplication, complain about forking an application that has multiple threads, and get stuck and never finish, presumably, for this reason.

Any hints on how I might be able to get rid of those threads & perform a full cleanup after QApplication?


Solution

  • I'm looking for a way to properly end these threads

    Short Answer.

    You can't

    Long Answer.

    Those threads which are still remains active after destruction of QApplication are definitely created by QApplication but those threads are created with detached mode on. See for more info. When any thread created with detached mode on it neither can join nor set back to join-able.

    To verify above check this code. This is point from where all integration plugins are created. Add break point here and step into code during debugging( in GDB). OR you can also set break point to function pthread_attr_setdetachstate.

    Now coming to solution of problem.

    Check this.

    The reason for the two death test styles has to do with thread safety. Due to well-known problems with forking in the presence of threads, death tests should be run in a single-threaded context.

    So google-test library developers are well aware about problem you facing and they have solution for such case too. Look here

    I believe this will helps you.