Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does QThread::quit() immediately end the thread or does it wait until returning to the event loop?

There are a lot of Qt multi-threading tutorials out there that state that a QThread can be stopped safely using the following two lines.

qthread.quit(); // Cause the thread to cease.
qthread.wait(); // Wait until the thread actually stops to synchronize.

I have a lot of code doing this, and in most cases of stopping thread, I'll always set my own cancel flag and check it often during execution (as is the norm). Until now, I was thinking that calling quit would perhaps cause the thread to simply no longer execute any waiting signals (e.g. signals that are queued will no longer have their slots called) but still wait on the currently executing slot to finish.

But I'm wondering if I was right or if quit() actually stops the execution of the thread where it's at, for instance if something is unfinished, like a file descriptor hasn't been closed, it definitely should be, even though in most cases my worker objects will clean up those resources, I'd feel better if I knew exactly how quit works.

I'm asking this because QThread::quit() documentation says that it's "equivalent to calling QThread::exit(0)". I believe this means that the thread would immediately stop where it's at. But what would happen to the stackframe that quit was called in?

like image 739
Joey Carson Avatar asked May 28 '14 23:05

Joey Carson


People also ask

What is the use of qthread quit?

QThread::quitdoes nothing if the thread does not have an event loop or some code in the thread is blocking the event loop. So it will not necessarily stop the thread. So QThread::quittells the thread's event loop to exit. After calling it the thread will get finished as soon as the control returns to the event loop of the thread.

Does quitting a thread stop the thread from running?

So it will not necessarily stop the thread. So QThread::quit tells the thread's event loop to exit. After calling it the thread will get finished as soon as the control returns to the event loop of the thread. You will have to add some kind of abort flag if you are blocking event loop for example by working in a loop.

What happens when qthread is called with termination disabled?

If termination has been deferred (i.e. QThread::terminate () was called with termination disabled), this function will terminate the calling thread immediately. Note that this function will not return in this case.

Can I add a new qthread slot to an existing qthread?

This means that all of QThread's queued slots and invoked methods will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.


2 Answers

QThread::quit does nothing if the thread does not have an event loop or some code in the thread is blocking the event loop. So it will not necessarily stop the thread.

So QThread::quit tells the thread's event loop to exit. After calling it the thread will get finished as soon as the control returns to the event loop of the thread.

You will have to add some kind of abort flag if you are blocking event loop for example by working in a loop. This can be done by a boolean member variable that is public or at least has a public setter method. Then you can tell the thread to exit ASAP from outside (e.g. from your main thread) by setting the abort flag. Of course this will require your thread code to check the abort flag at regular intervals.

You may also force a thread to terminate right now via QThread::terminate(), but this is a very bad practice, because it may terminate the thread at an undefined position in its code, which means you may end up with resources never getting freed up and other nasty stuff. So use this only if you really can't get around it. From its documentation:

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.

I think this is a good way to finish a thread when you are using loops in a thread:

myThread->m_abort = true; //Tell the thread to abort
if(!myThread->wait(5000)) //Wait until it actually has terminated (max. 5 sec)
{
  myThread->terminate(); //Thread didn't exit in time, probably deadlocked, terminate it!
  myThread->wait(); //We have to wait again here!
}
like image 170
Nejat Avatar answered Oct 29 '22 01:10

Nejat


In case, if you want to use Qt's builtin facility then try QThread::requestInterruption().

Main thread

struct X {
  QThread m_Thread; 
  void Quit ()
  {
    m_Thread.quit();
    m_Thread.requestInterruption();
  }
};

Some Thread referred by X::m_Thread

while(<condition>) {
  if(QThread::currentThread()->isInterruptionRequested())
    return;
  ...
}

As per the documentation:

void QThread::requestInterruption()

Request the interruption of the thread. That request is advisory and it is up to code running on the thread to decide if and how it should act upon such request. This function does not stop any event loop running on the thread and does not terminate it in any way.

like image 34
iammilind Avatar answered Oct 29 '22 01:10

iammilind