CPU Spinning occurs when a certain thread gets into either an infinite loop or is running a computation intesive operation that takes a long time. In both cases, the thread is “hogging” the CPU and the operating system cannot preempt and switch to run another thread of the same process (as it usually does).

The technique used to find out what is causing the CPU to spin is not native to .NET since both .NET code and native code can cause the CPU to spin. The only difference is that instead of looking at the native stack (using one of the “k” commands) we will use the !clrstack command to see the managed stack of the thread that is causing the problem.

This technique is very useful in live debugging, but can also be used in a post mortem situation using a memory dump taken by, for example, the customer.

In a live debugging situation when we attach to the relevant process the CPU is hogged by that process and it will take the debugger up to 30sec to wait for before forcibly breaking in.

Finding the rebellious thread
To find the rebellious thread, all we need to do is to run a command called !runaway.
The command will show us all the running threads in the CPU and how much CPU time they actually take.

The thread with the highest CPU time is usually the thread that is causing the spinning.

Of course, to actually be able to see this you will have to let the application run a bit in full CPU utilization so that rebellious thread will pop up in the !runaway list at the top.

Showing the thread’s stack
The thread ID shown in the !runaway command list is its true operating system ID and NOT its index (like you usually see and use when using the “~” comamnd).

To dump its stack we need to use the following syntax:
~~[Thread ID]e!clrstack
For example: ~~[2234]e!clrstack

The reason that we add the “e” is because !clrstack is a command that is not native to the debugger and it is implemented in a debugger extension (the SOS.dll extension).

If this is an unmanaged thread, we will use the following syntax:
~~[Thread ID]k
For example: ~~[2234]k

Of course, you can use any of the k command that is available (kb, kv, etc).

It’s that simple. No development environment needed. Nothing.
Just 2 commands and you can find the problematic code in no time.

Happying Spinning Fighting.

  • Marko Rangel

    Excellent post.

    An alternative approach, and also using the same concepts as the previous post, is to take a sequence of 2-4 hang dumps (using adplus.vbs -hang -p [pid]) and looking to see if the callstack is in the call frame or within the same function (could be a tight loop).

    Using the commands (!clrstack or any k command) you can see what the process is doing at different times to determine what is happening at different contexts.

  • First of all thanks for reading

    Second, you are correct, I usually combine what you have suggested with what I do. That verifies in 100% that this is indeed a CPU Spin situation.

    Thanks for pointing that out.