Yesterday I got a question to my Email from David Douglass, a reader of this blog.
David asked me how can he see the threads waiting on a certain managed lock and that he was trying to accomplish that using WinDbg and the SOS that shipped with .NET Framework 2.0.
I told David that he should use the !SyncBlk command and that I talked about it in a previous post but never actually used it in .NET Framework 2.0. I also suggested that if he is still having problems I’ll look into it a bit more using the sample I provided in the previous post.
Before I had a chance to do anything, David replied saying that he checked this issue with Tess Ferrandez (Tess is an Escalation Engineer in the PSS (Product Support Services) at Microsoft) and that the answer he got was that the version of SOS shipped with .NET Framework 2.0 does not have the ability to show on each managed lock which threads are waiting on it like the SOS that shipped in newer version of WinDbg.
When typing !help SyncBlk in WinDbg (after load the SOS extension of .NET 2.0 of course) the help states that there is a way to verify that, but it requires a bit of disassembling.
I think I found a better way of doing that and I’ll present it here. The code is based on the sample from the post about identifying dead lock in managed code and you can download the source code from here.
The sample I use here basically deadlocks two thread which are both waiting on resources held by the other thread.
Runing !SyncBlk shows me this:
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
12 0017a6a4 3 1 0018a1b0 efc 5 01371c38 System.Object
13 0017a6d4 3 1 00189df0 19f4 4 01371c2c System.Object
We see here that thread “efc” is the owner of the lock on SyncBlock 01371c38 and thread “19f4” is the owner of the lock on 01371c2c.
If we want to check which lock thread “efc” is trying to acquire all we need to do is run “~~[efc]kv” (do mind that I use kv to see the arguments being passed to the methods) and we should look for the method “mscorwks!JIT_MonEnterWorker_Portable“. If I’m not mistaken (and I do hope I’m not 😉 ), the first argument (the number showing on the “Args” column) should be the SyncBlock we are trying to acquire.
So in our case, on thread “efc” we should see that the first args of is “mscorwks!JIT_MonEnterWorker_Portable” 01371c2c.
I have not contacted anyone from Microsoft to validate my claims here (yet) but I will update the post if necessary.
Just a reminder: Do mind that when you will run the sample the addresses and thread number will probably be different.
If you are stuck in a problem or have a question, feel free to Email me to eran AT sandler . co . il and I’ll do my best to supply you with an answer.