George V. Reilly's Technical Blog

Never Sleep(0) in an Infinite Loop

I ran into a problem installing some COM+ components today. The installer was using Regsvcs.exe to register each COM+ component. I noticed after a while that the installer wasn't making any progress and that my dual-proc system was stuck at 50% CPU utilization. I attached a debugger to the offending process, regsvcs, and found that it was stuck in the following infinite loop (disassembly courtesy of Reflector):


internal void System.EnterpriseServices.CatalogSync.Wait()
{
if (this._set)
{
RegistryKey key1
= Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes\\CLSID");
while (true)
{
int num1 = (int) key1.GetValue("CLBVersion", 0);
if (num1 != this._version)
{
break;
}
Thread.Sleep(0);
}
this._set = false;
}
}


There are two severe problems with this code.

  1. The loop should time out. There must be some reasonable limit after which you can incontrovertibly say that something must have gone wrong, and throw an exception. There has to be some way to terminate a loop.

  2. Never use Sleep(0) in a loop. Sleep(0) yields the processor only if there's a runnable thread. If there isn't, Sleep(0) will return immediately. If the code is sitting in a tight loop, the net effect is that it will maximize the CPU until the thread's quantum is exhausted. There are no other runnable threads, so the scheduler immediately starts this thread again. This code will run until your CPU burns out.

(And, yes, I have committed both of these sins in shipping code. Why do you ask?)

I don't know what the calling code is doing or why CLBVersion isn't being altered by some other thread or process. I had to use RegEdit to modify this value to get the loop to terminate, whereupon RegSvcs immediately did its work and terminated. And then it started all over again, with the next invocation of RegSvcs on another COM+ component. I don't know if the components are really installed properly. I had to leave at that point.

Posted: Sep 13 2006, 11:53 PM by george_v_reilly | with 2 comment(s)
Filed under:

Comments

Travis said:

Hello everyone. Summer afternoon - Summer afternoon. the two most beautiful words in the English language. Help me! I can not find sites on the: Book of mephisto. I found only this - <a href="advancedmaritimetechnology.aticorp.org/.../Mephisto">mephisto master versus novag diamond</a>. At world the claws play terrance has made a blue spirtualism, mephisto. Mephisto, often especially, most riders and some survivors think that other men are though special with hunter. With love :mad:, Travis from Scotland.

# March 23, 2010 1:12 AM

Bob Morley said:

This is a really old blog; but we ran into the same problem working with some older software.  What I found was that RegSvcs would create a Sync object that would record the current value of CLBVersion using an HKLM\SOFTWARE\Classes\CLSID path.  It would then trigger registration of the component that is handled by the COM+ System Application service (running under dllhost).

On a machine that was not hanging it, dllhost would update HKCR\CLSID\CLBVersion. Once it did this RegSvcs would fall out of the loop and away things go.  However, on my machine that was not working it would attempt to update HKCU\CLSID\CLBVersion (which does not appear to exist) and leave RegSvcs in its infinite loop.

Intersetingly, manually updating the registry did not cause things to resume -- but in the debugger I could force it to fall out of the loop and complete (very painful).

# May 18, 2011 1:40 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)