0

I want to terminate (finish) a QThread, when my app will be destroyed. So I invoke terminate() and quit() within a destructor of my derived class from `QThread. Is it safe?

class Session : public QThread
{
    Q_OBJECT

private:
    CheckerAdapter *inst;

public:
    explicit Session(CheckerAdapter *inst, QObject *parent = 0);
    void run();

    ~Session(){
        terminate();
        quit();
    }
};
Bob
  • 1,433
  • 1
  • 16
  • 36

1 Answers1

6

Using QThread::terminate() can lead to memory corruption, since the thread is just terminated without its knowledge, it can be doing anything while it gets terminated:

Warning: This function is dangerous and its use is discouraged. The thread can be terminated at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to clean up after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.

To safely terminate a QThread, You need to have a way to tell the thread that it has to terminate, and when the thread gets that, it should return from its run() implementation as soon as possible. Qt provides two ways to do this:

  • If your thread runs an event loop (i.e. You don't override run(), Or if you call exec() in your custom run() implementation), You can call QThread::quit()/QThread::exit() from any thread. This will cause the thread event's loop to return as soon as it finishes processing current events. There is no data corruption, as current processing doesn't get terminated.
  • If your thread does not run an event loop, You can use QThread::requestInterruption() from any other thread to tell the thread that it should stop. But you have to handle that in your implementation of run() using isInterruptionRequested()(otherwise, calling requestInterruption() will do nothing).

Note:

If you are using any of the above methods to stop your QThread in its destructor, You have to make sure that the thread is no longer running after the QThread object gets destructed, You can do that by calling QThread::wait() after using quit()/requestInterruption().

Have a look at this answer for a similar implementation of a QThread subclass.

Community
  • 1
  • 1
Mike
  • 8,055
  • 1
  • 30
  • 44