A couple of years ago I gave a cursory visit to the subject of diagnosing a Monitor-based deadlock in a managed application, and then a few months ago I demonstrated in greater detail how to locate the synchronization object your thread is waiting for using SOS. [Side note: It’s always easy to see the list of currently owned Monitors (sync blocks) using the SOS !SyncBlk command, which also tells you which thread owns each synchronization object. The hard part is to find the synchronization object for which your thread is waiting if you don’t have any prior knowledge of this particular lock your application is using.] It’s always good to have another way of doing the same thing, in case something doesn’t work out in the debugger. This post shows a third approach to detecting the synchronization object for which your thread is waiting. After attaching to the process, use !Threads, !CLRStack, and !SyncBlk as usual to see the general picture. In this example, here are the threads (edited for brevity):0:004> !Threads
ThreadCount: 3
...
ID OSID APT Exception
0 1 1320 MTA
2 2 fec MTA (Finalizer)
3 3 18d8 MTA (Threadpool Worker)OK, so we have a few of threads here, one is the main thread, the other is the finalizer thread, and the third is a thread pool thread. Here’s the call stack for the application’s threads (edited for brevity, e.g. I removed the unmanaged threads): 0:004> ~* e !CLRStack
OS Thread Id: 0x1320 (0)
Child-SP RetAddr Call Site
000000000013ee10 000007fef7d8d502 LocksAndLocks.Program.Main()
OS Thread Id: 0xfec (2)
Failed to start stack walk: 80004005
OS Thread Id: 0x18d8 (3)
Child-SP RetAddr Call Site
000000001aecf510 000007fef6c72bbb …c__DisplayClass1.<Main>b__0(…)
000000001aecf560 000007fef6ce7411 System.Threading.ExecutionContext.Run(…)
000000001aecf5b0 000007fef6ce724f …PerformWaitCallbackInternal(…)
000000001aecf600 000007fef7d8d502 …PerformWaitCallback(…)“Failed to start stack walk”—in other words, the finalizer thread is not currently executing any managed code. Not interesting. And here are the sync blocks (edited for brevity):0:004> !syncblk
SyncBlock Owning Thread SyncBlock Owner
0000000000c38408 3 0000000002683a98 System.StringWhat is this string anyway? Read more: All Your Base Are Belong To Us
ThreadCount: 3
...
ID OSID APT Exception
0 1 1320 MTA
2 2 fec MTA (Finalizer)
3 3 18d8 MTA (Threadpool Worker)OK, so we have a few of threads here, one is the main thread, the other is the finalizer thread, and the third is a thread pool thread. Here’s the call stack for the application’s threads (edited for brevity, e.g. I removed the unmanaged threads): 0:004> ~* e !CLRStack
OS Thread Id: 0x1320 (0)
Child-SP RetAddr Call Site
000000000013ee10 000007fef7d8d502 LocksAndLocks.Program.Main()
OS Thread Id: 0xfec (2)
Failed to start stack walk: 80004005
OS Thread Id: 0x18d8 (3)
Child-SP RetAddr Call Site
000000001aecf510 000007fef6c72bbb …c__DisplayClass1.<Main>b__0(…)
000000001aecf560 000007fef6ce7411 System.Threading.ExecutionContext.Run(…)
000000001aecf5b0 000007fef6ce724f …PerformWaitCallbackInternal(…)
000000001aecf600 000007fef7d8d502 …PerformWaitCallback(…)“Failed to start stack walk”—in other words, the finalizer thread is not currently executing any managed code. Not interesting. And here are the sync blocks (edited for brevity):0:004> !syncblk
SyncBlock Owning Thread SyncBlock Owner
0000000000c38408 3 0000000002683a98 System.StringWhat is this string anyway? Read more: All Your Base Are Belong To Us
0 comments:
Post a Comment