December 9th, 2003

Why you should never suspend a thread

It’s almost as bad as terminating a thread.

Instead of just answering a question, I’m going to ask you the questions and see if you can come up with the answers.

Consider the following program, in (gasp) C#:

using System.Threading;
using SC = System.Console;
class Program {
  public static void Main() {
    Thread t = new Thread(new ThreadStart(Program.worker));
    t.Start();
    SC.WriteLine("Press Enter to suspend");
    SC.ReadLine();
    t.Suspend();
    SC.WriteLine("Press Enter to resume");
    SC.ReadLine();
    t.Resume();
  }
  static void worker() {
    for (;;) SC.Write("{0}\r", System.DateTime.Now);
  }
}

When you run this program and hit Enter to suspend, the program hangs. But if you change the worker function to just “for(;;) {}” the program runs fine. Let’s see if we can figure out why.

The worker thread spends nearly all its time calling System.Console.WriteLine, so when you call Thread.Suspend(), the worker thread is almost certainly inside the System.Console.WriteLine code.

Q: Is the System.Console.WriteLine method threadsafe?

Okay, I’ll answer this one: Yes. I didn’t even have to look at any documentation to figure this out. This program calls it from two different threads without any synchronization, so it had better be threadsafe or we would be in a lot of trouble already even before we get around to suspending the thread.

Q: How does one typically make an object threadsafe?

Q: What is the result of suspending a thread in the middle of a threadsafe operation?

Q: What happens if – subsequently – you try to access that same object (in this case, the console) from another thread?

These results are not specific to C#. The same logic applies to Win32 or any other threading model. In Win32, the process heap is a threadsafe object, and since it’s hard to do very much in Win32 at all without accessing the heap, suspending a thread in Win32 has a very high chance of deadlocking your process.

So why is there even a SuspendThread function in the first place?

Debuggers use it to freeze all the threads in a process while you are debugging it. Debuggers can also use it to freeze all but one thread in a process, so you can focus on just one thread at a time. This doesn’t create deadlocks in the debugger since the debugger is a separate process.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.