18

Recently ,I come across this problem as I memtioned in this Title. I have tried by using QThread::terminate(),but I just can NOT stop the thread ,which is in a dead loop (let's say,while(1)).

thanks a lot.

ChrisV
  • 3,363
  • 16
  • 19
user230938
  • 191
  • 1
  • 1
  • 4
  • Retagged to add the more common "qt" tag. – ChrisV Dec 14 '09 at 03:57
  • 3
    The Qt doc says:"Warning: This function is dangerous and its use is discouraged. The thread can be terminate at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to cleanup after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary. Termination can be explicitly enabled or disabled by calling QThread::setTerminationEnabled(). Calling this function while termination is disabled results in the termination being deferred, until termination is re-enabled." – yan bellavance Feb 26 '10 at 23:59

5 Answers5

12

Terminating the thread is the easy solution to stopping an async operation, but it is usually a bad idea: the thread could be doing a system call or could be in the middle of updating a data structure when it is terminated, which could leave the program or even the OS in an unstable state.

Try to transform your while(1) into while( isAlive() ) and make isAlive() return false when you want the thread to exit.

rpg
  • 7,746
  • 3
  • 38
  • 43
  • Hi,rpg. The example of while(1) is just one case. What I really want is to terminate the thread which is doing a heavy computation that will last very very long. I just want to stop it before it finishing excution. Thanks. ps:I saw a clue that Rocknroll gives --use pipe to stop a Qthread.But I never find the solution. – user230938 Dec 15 '09 at 07:14
  • Try adding something similar to interruption points in your heavy computation function: http://www.justsoftwaresolutions.co.uk/threading/thread-interruption-in-boost-thread-library.html – rpg Dec 15 '09 at 09:18
  • Yes, I agree with what is said here. Terminating a thread by the hard way is never a good thing. – Ignacio Soler Garcia Jan 19 '10 at 07:47
1

QThreads can deadlock if they finish "naturally" during termination.

For example in Unix, if the thread is waiting on a "read" call, the termination attempt (a Unix signal) will make the "read" call abort with an error code before the thread is destroyed.

That means that the thread can still reach it's natural exit point while being terminated. When it does so, a deadlock is reached since some internal mutex is already locked by the "terminate" call.

My workaround is to actually make sure that the thread never returns if it was terminated.

while( read(...) > 0 ) {

  // Do stuff...
}

while( wasTerminated )
  sleep(1);

return;

wasTerminated here is actually implemented a bit more complex, using atomic ints:

enum {

  Running, Terminating, Quitting
};

QAtomicInt _state; // Initialized to Running

void myTerminate()
{
  if( _state.testAndSetAquire(Running, Terminating) )
    terminate();
}

void run()
{
  [...]

  while(read(...) > 0 ) {

    [...]
  }

  if( !_state.testAndSetAquire(Running, Quitting) ) {
    for(;;) sleep(1);
  }
}
hmn
  • 716
  • 7
  • 18
0

Have you tried exit or quit?

Marius
  • 57,995
  • 32
  • 132
  • 151
  • quote from QT help doc:"This function does nothing if the thread does not have an event loop" It might work, in the case of an event loop. But if I want to terminate it before thread finishes its work, How should I do? thanks a lot. My dear. – user230938 Dec 14 '09 at 02:38
  • In fact those 2 functions are actually used to return from an event loop when exec has been called. – yan bellavance Feb 27 '10 at 00:01
0

Did the thread call QThread::setTerminationEnabled(false)? That would cause thread termination to delay indefinitely.

EDIT: I don't know what platform you're on, but I checked the Windows implementation of QThread::terminate. Assuming the thread was actually running to begin with, and termination wasn't disabled via the above function, it's basically a wrapper around TerminateThread() in the Windows API. This function accepts disrespect from no thread, and tends to leave a mess behind with resource leaks and similar dangling state. If it's not killing the thread, you're either dealing with zombie kernel calls (most likely blocked I/O) or have even bigger problems somewhere.

ChrisV
  • 3,363
  • 16
  • 19
0

To use unnamed pipes

int gPipeFdTest[2];  //create a global integer array

As an when where you intend to create pipes use

if( pipe(gPipeFdTest) < 0)

{

perror("Pipe failed");

exit(1);

}

The above code will create a pipe which has two ends gPipeFdTest[0] for reading and gPipeFdTest[1] for writing. What you can do is in your run function set up to read the pipe using select system call. And from where you want to come out of run, there set up to write using write system call. I have used select system call for monitoring the read end of the pipe as it suits my implmentation. Try to figure all this out in your case. If you need any more help, give me a buzz.

Edit:

My problem was just like yours. I had a while(1) loop and the other things I tried needed mutexes and other fancy multithreading mumbo jumbo, which added complexity and debugging was nightmare. Using pipes absolved me from those complexities besides simplified the code. I am not saying that it is the best option but in my case it turned out to be the best and cleanest alternative. I was bugged my hung application before this solution.

rocknroll
  • 1,128
  • 2
  • 15
  • 30