Adi Levin's Blog for programmers

September 19, 2009

Ending a thread

Filed under: Multithreading — Adi Levin @ 1:59 pm
Tags: , , ,

There are three ways to end a thread: Return from the thread function, call ExitThread from within the thread, and call TerminateThreadfrom any thread. The best thing to do is return from the thread function. This way, you guarantee that all destructors of automatic variables have been called, and that thread termination is done properly.

TerminateThread – never use it!

BOOL WINAPI TerminateThread(
  __inout  HANDLE hThread,
  __in     DWORD dwExitCode
);

Some programmers make the mistake of waiting with a timeout until a thread is finished, and then kill it using TerminateThread in case of timeout. Don’t do that! TerminateThread terminates the thread immediately without doing the proper clean-up and notifications. It doesn’t free the stack (1Mb leak), it doesn’t free owned critical sections, it doesn’t call the DLL entry functions to notify them that the thread is being detached. Of course, it doesn’t give the thread a chance to free objects allocated on the heap.

The result is a potential deadlock, and the worst thing is that it happens with low probability, so there is a good chance that software testing will not detect it, and your customer will be the first to encounter it. Why a potential deadlock? Because certain library functions (such as malloc, free and MFC functions), use critical sections to synchronize access of threads within the process to certain resources (such as the heap). This means that whenever you call malloc you are waiting for a critical section to be released. But if you called TerminateThread while that thread owned that critical section, the wait will result in a dead-lock.

In fact, there is no justification to using TerminateThread. It is only safe to use when you control exactly what that thread is doing (e.g. you know that it doesn’t do heap allocation, and it is not inside a critical section). But if you are the programmer of that thread’s function, then why not write code that returns safely from the thread function upon some event or flag, or calls ExitThread when needed?

ExitThread – use it with care!

ExitThread can only be called from within the thread which you want to exit. It frees the stack and calls the entry point of each DLL in the process to notify it that the thread is being detached. However, it does not perform destruction of C++ objects as done when returning from a function. This is why you have to use it with care.

In certain situations, it make sense to use ExitThread for the purpose of simplifying the code. For example, if the thread is in alertable state (i.e. waits for APC functions), other threads can queue an APC function that calls ExitThread, thereby causing the thread to exit.

The best way: Returning from the thread function

The best way to write a thread function is to design it so that another thread (the main thread, or the thread that is managing the worker threads), can cause it to end in an orderly fashion.

 For example, if you run a loop with many iterations, check the value of a certain flag in each iteration, and return if it is non-zero. Other threads can change the value of that flag when they want your thread to finish.

 

If your thread waits for some object to be signaled, using WaitForSingleObject(obj,…), and you want to be able to stop the wait from another thread, replace the wait function by WaitForMultipleObjects, and wait for obj and for an event that can be signaled by another thread, when termination is needed.

More generally, in any point in the code where you want to be able to interrupt the operation of the thread and cause it to exit, you should place the appropriate code.

Create a free website or blog at WordPress.com.