ExitThread() in managed program?

I’ve seen people calls OS’s ExitThread in managed applications via PInvoke to exit a managed thread, like this:

[DllImport( “Kernel32.dll”)]
public static extern void ExitThread(int exitCode);

public static void Run ()
    // calling OS’s ExitThread to exit the current thread
    ExitThread (0);

public static void Main ()
    ThreadStart threadStart = new ThreadStart(Run);
    Thread thread = new Thread(threadStart);

I guess when unmanaged code is ported to managed code, people tends to translate every system call to a PInvoke. But because CLR provides another layer over the OS, some low level system calls don’t make sense in the managed world. ExitThread is one of them, because managed threads are not equivlent to OS’s native threads. The above code is wrong for 2 reasons:

  1. CLR has some clean up work (like stack unwinding) to do when a managed thread exits. CLR knows a managed thread is exiting when the thread procedure (like threadStart) returns or a ThreadAbortException is thrown. Calling OS’s ExitThread (or even worse, TerminateThread) would bypass all back out code on the stack (such as destructor and finally block) and leave the program in an unspecified state.
  2. There is no guarantee about how CLR maps a managed/logical thread to an OS/physical thread. For example, several managed threads could be mapped to one OS thread, calling ExitThread in one managed thread might kill other managed threads unintentionally.

IMHO, calling system’s ExitThread in managed program is almost always a mistake. Instead, we could just call Thread.Abort.


This posting is provided “AS IS” with no warranties, and confers no rights.

Comments (3)

  1. I’d say yes, it is almost always a mistake. However, there are circumstances where a managed thread becomes unusable or the Abort method doesn’t work or takes a long time to actually clean up the thread. I know there are certain types of stack overflow conditions under V1 and V1.1 that caused this situation to occur and you have to use a PInvoke to kill the thread. Unfortunately managed threads aren’t nearly as robust as native threads.

  2. Yun Jin says:

    Very interesting point. Indeed V1 and V1.1 ARE not reliable in face of OutOfMemoryException and StackOverflowException. I could imagine that you might have trouble to unwind a thread appropriately under such conditions. Improving robustness is an important goal for Whidbey. In Whidbey, big efforts are invested to handle OutOfMemoryException and StackOverflowException in every corner of CLR. Chris Brumme has several great posts about this topic in his blog.

    When Whidbey is shipped, it’s supposed to be reliable enough to run in SQL server. So I hope your problem would be solved then. 🙂