Karl Cassar
Karl Cassar

Reputation: 6483

slow/hanging Asp.net web application - full dump shows several threads waiting for lock

I have a web application and sometimes it is hanging / performing very slow. I have taken a full dump using DebugDiag, and tried to analyse it using the Crash/Hang analysis.

The summary gave me that 7.86% of my threads (10) are blocked and waiting for Monitor.Wait.

However, when I check the Call Stack / Stack Trace with the thread, the below is outputted:

.NET Call Stack



Function 
System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object) 
System.Threading.Monitor.Wait(System.Object, Int32, Boolean) 
Quartz.Simpl.SimpleThreadPool+WorkerThread.Run() 
System.Threading.ThreadHelper.ThreadStart_Context(System.Object) 
System.Threading.ExecutionContext.runTryCode(System.Object) 
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object) 
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
System.Threading.ThreadHelper.ThreadStart() 


Full Call Stack



Function   Source 
ntdll!NtWaitForMultipleObjects+15    
KERNELBASE!WaitForMultipleObjectsEx+100    
kernel32!WaitForMultipleObjectsExImplementation+e0    
clr!WaitForMultipleObjectsEx_SO_TOLERANT+56    
clr!Thread::DoAppropriateAptStateWait+4d    
clr!Thread::DoAppropriateWaitWorker+17d    
clr!Thread::DoAppropriateWait+60    
clr!CLREvent::WaitEx+106    
clr!CLREvent::Wait+19    
clr!Thread::Wait+1d    
clr!Thread::Block+1a    
clr!SyncBlock::Wait+169    
clr!ObjHeader::Wait+2c    
clr!ObjectNative::WaitTimeout+147    
System.Threading.Monitor.Wait(System.Object, Int32, Boolean)    
System.Threading.ThreadHelper.ThreadStart_Context(System.Object)    
System.Threading.ExecutionContext.runTryCode(System.Object)    
clr!CallDescrWorker+33    
clr!CallDescrWorkerWithHandler+8e    
clr!MethodDesc::CallDescr+194    
clr!MethodDesc::CallTargetWorker+21    
clr!MethodDescCallSite::Call+1c    
clr!ExecuteCodeWithGuaranteedCleanupHelper+bb    
clr!ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup+138    
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)    
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)    
System.Threading.ThreadHelper.ThreadStart()    
clr!CallDescrWorker+33    
clr!CallDescrWorkerWithHandler+8e    
clr!MethodDesc::CallDescr+194    
clr!MethodDesc::CallTargetWorker+21    
clr!ThreadNative::KickOffThread_Worker+1e1    
clr!Thread::DoExtraWorkForFinalizer+114    
clr!Thread::ShouldChangeAbortToUnload+101    
clr!Thread::ShouldChangeAbortToUnload+399    
clr!Thread::RaiseCrossContextException+3f8    
clr!Thread::DoADCallBack+358    
clr!Thread::DoExtraWorkForFinalizer+fa    
clr!Thread::ShouldChangeAbortToUnload+101    
clr!Thread::ShouldChangeAbortToUnload+399    
clr!Thread::ShouldChangeAbortToUnload+43a    
clr!ManagedThreadBase::KickOff+15    
clr!ThreadNative::KickOffThread+23e    
clr!Thread::intermediateThreadProc+4b    
kernel32!BaseThreadInitThunk+e    
ntdll!__RtlUserThreadStart+70    
ntdll!_RtlUserThreadStart+1b 

It doesn't actually show me which lock they are waiting to obtain - Any idea on how to get this information?

Upvotes: 0

Views: 3796

Answers (1)

sugaredlightning
sugaredlightning

Reputation: 131

Unfortunately it looks like the thread doesn't go very many methods deep before calling Monitor.Wait, so it may be harder to pinpoint the exact location. Based off the stack trace, look at the code for Quartz.Simpl.SimpleThreadPool+WorkerThread.Run() and see where it calls Monitor.Wait to see what it is actually waiting on.

Depending on the volume/quality of code, that is probably the easy way. You could also install Windbg, locate the address of the object it is locking on, and examine it, but there's some initial configuration required to make sure it can load up all the symbols it needs. http://blogs.msdn.com/b/emeadaxsupport/archive/2011/04/10/setting-up-windbg-and-using-symbols.aspx talks about Windbg setup. It is a powerful tool, but just checking the code for Quartz.Simpl.SimpleThreadPool+WorkerThread.Run() will probably be simpler.

Upvotes: 1

Related Questions