3.2.4 Terminating a Thread

A thread created by CreateThread executes until it calls ExitThread or until the thread function returns (in which case, ExitThread is called implicitly). The argument to ExitThread (or the value returned by the thread function) is the exit code of the thread. Other threads with a handle to the thread can determine the exit code by calling GetExitCodeThread. When a thread terminates as a result of an explicit or implicit call to ExitThread, the thread's stack is deallocated, any attached DLL's are notified of the thread's termination, and the state of the thread object becomes signalled, releasing any waiters on the thread.

The primary thread of a process differs from the other threads of a process in that ExitProcess (rather than ExitThread ) is called implicitly when it returns. This terminates all threads of the process without notifying any attached DLL's of a thread's termination or giving any thread a chance to execute additional code. This means that if any of the terminated threads are in the middle of executing the “try” block of a try-finally or try-except structured exception handler, the finally or except blocks will not be executed. The primary thread can avoid terminating other threads by explicitly calling ExitThread when it wants to exit, but in this case, one of the remaining threads should explicitly call ExitProcess. If ExitProcess is not invoked either implicitly by the primary thread or explicitly by any thread, it is possible that the process will not terminate even though all threads known to the application have terminated. The problem occurs when an attached DLL creates a thread that is terminated only when the DLL is notified of the process's termination by ExitProcess. For example, for console applications, a thread like this is created to handle Ctrl-C.

The argument to ExitProcess (or the value returned by the main function) is the exit code of the process. Other threads with a handle to the process can determine the exit code by calling GetExitCodeProcess . If a process is terminated in some other way than by calling ExitProcess (for example, a fatal unhandled exception or a Ctrl-C from the user) the process termination code be the exception code that caused the termination.

A thread can also be terminated if its handle is specified in a call to TerminateThread. This terminates the thread without notifying attached DLLs or allowing it to execute any termination code.

Calling either ExitThread, ExitProcess, or TerminateThread from within the “try” block of a “try-finally” structured exception handler will prevent the finally block from being executed.

try {

.

.

.

ExitThread(0); /* doesn't return, so "finally" not executed */

} finally {

printf("this will not get printed\\n");

}

However, if the thread function simply returns instead of calling ExitThread, the return will cause a termination of the try block which causes the finally block to execute as part of the block exit sequence. After the finally block has been executed, the return from the thread procedure completes with the implicit call of ExitThread.

try {

.

.

.

return 0;

} finally {

printf("this will get printed\\n");

}