Search code examples
lockingdeadlockwindbgdump

How to find a deadlock?


I'm trying to follow the procedure, explained under this Microsoft link, for finding a possible deadlock in my application.

In my case, I also start with the function !locks:

CritSec +1130780 at 01130780
WaiterWoken        No
LockCount          0
RecursionCount     1
OwningThread       1624
EntryCount         0
ContentionCount    8
*** Locked

CritSec Wldap32!SelectLock1+0 at 7630a1b0
WaiterWoken        No
LockCount          1
RecursionCount     1
OwningThread       30d8
EntryCount         0
ContentionCount    219
*** Locked

CritSec Wldap32!SelectLock2+0 at 7630a168
WaiterWoken        No
LockCount          0
RecursionCount     1
OwningThread       1624
EntryCount         0
ContentionCount    47d
*** Locked

CritSec +cd6838 at 00cd6838
WaiterWoken        No
LockCount          1
RecursionCount     1
OwningThread       4584
EntryCount         0
ContentionCount    184
*** Locked

Scanned 107 critical sections

The second item mentions I need to go for thread 30d8:

0:000> ~
...
  59  Id: 3ff4.30d8 Suspend: 0 Teb: fe2a5000 Unfrozen
...

So, I might expect information about a critical section in thread 59, but while looking there:

  59  Id: 3ff4.30d8 Suspend: 0 Teb: fe2a5000 Unfrozen
 # ChildEBP RetAddr  Args to Child              
00 0a48f4c4 74de9220 000036b8 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
01 0a48f574 74df376d 0d7acba0 00000000 00000000 IPHLPAPI!IcmpSendEcho2Ex+0x208
02 0a48f5ac 74df37a7 0d7acba0 00000000 00000000 IPHLPAPI!IcmpSendEcho2+0x2d
03 0a48f5e0 76303545 0d7acba0 bdd2500a 0a48f61f IPHLPAPI!IcmpSendEcho+0x27
04 0a48f6c0 762e0a46 0a48f79c 0c2180a0 0a08d660 Wldap32!LdapPingServer+0xa1
05 0a48f708 762c4ca0 00001363 0c3f2ba0 00000000 Wldap32!DrainWinsock+0x1c69a
06 0a48f778 762c6eae 00002774 00000000 0a48f79c Wldap32!LdapWaitForResponseFromServer+0x767
07 0a48f7d0 762c7bf9 00000000 0a48f850 0a48f9d4 Wldap32!ldap_result_with_error+0xf2
08 0a48f7f8 002c3a9b 0a08d88c 00001363 00000000 Wldap32!ldap_result+0x59
09 0a48faf8 002bcc1e 04059930 569939a1 00c21220 <Application>!CActiveDirectoryInfo::LDAPNotificationFunc+0xe5b
0a 0a48fb24 002c41a0 04059930 569939e5 7437f28e <Application>!CActiveDirectoryInfo::LDAPNotification_Protected+0xbe
0b 0a48fb60 7437f2e9 04059930 22a3f765 7437f28e <Application>!LDAPNotification+0x50
0c 0a48fb98 7437f2cd 7437f28e 0a48fbb8 75547c04 msvcr110!_beginthreadex+0xb4
0d 0a48fba4 75547c04 026f2b28 75547be0 238314af msvcr110!_endthreadex+0x102
0e 0a48fbb8 77d9ad2f 026f2b28 21045533 00000000 kernel32!BaseThreadInitThunk+0x24
0f 0a48fc00 77d9acfa ffffffff 77d800c7 00000000 ntdll!__RtlUserThreadStart+0x2f
10 0a48fc10 00000000 7437f28e 026f2b28 00000000 ntdll!_RtlUserThreadStart+0x1b

Edit after first comment:

Unfortunately the command sosex.dlk did not reveal any information, even after having run the !bhi command.

As far as investigating 36b8, also there there's not much information:

0:000> !handle 36b8 f
Handle 000036b8
  Type          Event
  Attributes    0
  GrantedAccess 0x1f0003:
         Delete,ReadControl,WriteDac,WriteOwner,Synch
         QueryState,ModifyState
  HandleCount   2
  PointerCount  65538
  Name          <none>
  Object specific information
    Event Type Auto Reset
    Event is Waiting

I'm not aware of the !findstack feature, can you tell me what I'm doing wrong here?

0:000> !findstack CriticalSection
0:000> !findstack *!CriticalSection
0:000> !findstack RtlEnterCriticalSection
0:000> !findstack *CriticalSection*
=> always no results.

Solution

  • Thread 59 is owning the critical section already. That means it has called EnterCriticalSection some time ago. You'll not see that in the debugger any more. That thread should call LeaveCriticalSection somewhen. But at the moment it's waiting for something else to happen (WaitForSingleObject on object 36b8).

    Next steps:

    • find out what 36b8 is, using !handle 36b8 f.
    • a different thread than 59 might be waiting on that critical section. So watch out for EnterCriticalSection using !findstack.

    If you suspect the deadlock to be caused by critical sections only, you can use !sosex.dlk. Although SOSEX was designed for .NET deadlocks, it can also detect deadlocks in critical sections.