Thursday, February 21, 2013

How to Debug a Deadlock in KD & WinDBG

In my last post, I was looking at some threads in KD and noticed there was a deadlock.  I will quickly go through the analysis of that particular deadlock.  You can review that post here.

As a quick review, I dumped the stacks of the running threads in the process.  The one that we knew was hung, was waiting to be notified.  Then the problem thread that was supposed to notify was hung waiting on an object.  Inspecting the stack led us to frame 9.  Looking at the source:


DWORD WINAPI CNotificationQueue::ThreadProc( void * pv )
{
...
        while ( 0 == s_lThreadShuttingDown )
        {
            EnterCriticalSection( &s_cs );
            poNotification = RemoveHead();
            if ( poNotification )

We can see this code is taking a lock on s_cs, a global.  

0: kd> ?? CNotificationQueue::s_cs

struct _RTL_CRITICAL_SECTION
   +0x000 DebugInfo        : 0x026acca0 _RTL_CRITICAL_SECTION_DEBUG
   +0x004 LockCount        : 0n-1
   +0x008 RecursionCount   : 0n0
   +0x00c OwningThread     : (null)
   +0x010 LockSemaphore    : 0x00000558 Void
   +0x014 SpinCount        : 0x20007d0
0: kd> !cs 0x026acca0
-----------------------------------------
Critical section   = 0x026acca0 (+0x26ACCA0)
Uninitialized or deleted.
LOCKED
LockCount          = 0xE4C5EB20
WaiterWoken        = Yes
OwningThread       = 0x00857380
RecursionCount     = 0x2658C70
LockSemaphore      = 0x0
SpinCount          = 0x00000031
0: kd>

So, this code is taking a lock on an invalid critical section, and hangs.  At this point if this bug reproduces, it would be good to run this again with Application Verifier enabled on the faulty code.

No comments:

Post a Comment