Debugging

  • Thread starter Thread starter Zachary Turner
  • Start date Start date
Z

Zachary Turner

I have a situation with an apparent deadlock. I have two threads
which are blocked on the statement "lock(_SyncRoot)", where _SyncRoot
is my own private object. However, I've examined all the other
threads in my application and walked up their callstacks, and none of
them seem to be holding a lock on this object. Moreoever, I never
lock this object in any way other than using the lock keyword, and
it's never in a nested lock. So it seems to me that a deadlock is
provably not possible.

Is there some sort of debugger command that will tell me which thread
is holding the lock on this object?

Thanks
 
Break every time it locks that object and when it releases the lock. When it
fires a second lock, you can backtrace on the call stack and figure where to
set a breakpoint. Most likely you are calling the routine a second time
before the lock is gone or some error is preventing letting the lock loose.

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

*********************************************
Think outside the box!
*********************************************
 
Calling the routine a second time before the lock is gone shouldn't
cause a problem should it? It would simply wait at the lock statement
until the first routine releases the lock, then it will enter.
Moreover, lock statements are internally embedded in try/finally so
they are always released no matter how the block is exited.

I'm actually starting to think my system may have more severe
problems, of which this could be a side effect. Ugh.
 
Zachary Turner said:
I have a situation with an apparent deadlock. I have two threads
which are blocked on the statement "lock(_SyncRoot)", where _SyncRoot
is my own private object. However, I've examined all the other
threads in my application and walked up their callstacks, and none of
them seem to be holding a lock on this object. Moreoever, I never
lock this object in any way other than using the lock keyword, and
it's never in a nested lock. So it seems to me that a deadlock is
provably not possible.

Is there some sort of debugger command that will tell me which thread
is holding the lock on this object?

One thing you could do is replace the existing lock with a "smart" lock
as per
http://pobox.com/~skeet/csharp/miscutil/usage/locking.html
If you use an OrderedLock, it will keep track of who's got hold of it,
so you could debug it that way.

It shouldn't be too hard to replace the lock if it's only locked in a
single class, and you can put it back afterwards if you want. Of
course, you'd need to use the MiscUtil library temporarily. You can get
it from:
http://pobox.com/~skeet/csharp/miscutil
 
Zachary Turner said:
Is there some sort of debugger command that will tell me which thread
is holding the lock on this object?

There sure is. Unfortunatly, it only exists in WinDbg & Son of Strike - not
in Visual Studio.
http://msdn.microsoft.com/msdnmag/issues/05/07/Debugging/?topics=/msdnmag/issues/05/07/Debugging#S11

You should be able to track it down pretty quickly, once you get over the
"eeewwww!" factor that comes with WinDbg.

Generating a dump one your application is hung is pretty easy. You can read
about it either in the article I already linked, or at:
http://www.coversant.net/Coversant/Blogs/tabid/88/EntryID/28/Default.aspx

(If you're able to consistanly get your app to deadlock, you should be able
to skip the whole 'Create a Dump" step, and just run your app using WinDbg &
SOS. That makes things a bit easier.)
 
I'm familar with WinDbg already, but it only operates on primitive
windows threads. My understanding of .NET Threads is that there is no
defined mapping between a .NET Thread and the Windows thread(s) by
which it is implemented. In fact, 4 different .NET Threads may be
implemented on a single windows thread, or 1 different .NET Thread may
be implemented by 4 Windows threads. I may be wrong about that, but I
never considered the WinDbg option simply because even if I found out
which Windows thread was holding the object, I wouldn't be able to map
that back to one of my .NET threads.
 
The definition of CLR threads in the leaves room for exactly what you
describe, but today's reality is that a CLR thread & an O/S thread are the
same thing in all current implementations of the CLR. As a result, you don't
have to worry about the details of CLR threads mapped to O/S threads. I
recently confirmed this by talking to both Joe Duffy & Jeff Richter. I
talked a bit about this in this thread:
http://groups.google.com/group/micr..._frm/thread/c37841cfe5a1dd01/cc648b16583c6fa4

Also, WinDbg, when you use Son of Strike with it, gives you all the
debugging information you need. It's loaded with stuff. When you say,
"!threads", you get a list of CLR threads, and their details.

Using WinDbg & SOS, you should be able to track this down pretty easily.

--
Chris Mullins, MCSD.NET, MCPD:Enterprise, Microsoft C# MVP
http://www.coversant.com/blogs/cmullins

Zachary Turner said:
I'm familar with WinDbg already, but it only operates on primitive
windows threads. My understanding of .NET Threads is that there is no
defined mapping between a .NET Thread and the Windows thread(s) by
which it is implemented. In fact, 4 different .NET Threads may be
implemented on a single windows thread, or 1 different .NET Thread may
be implemented by 4 Windows threads. I may be wrong about that, but I
never considered the WinDbg option simply because even if I found out
which Windows thread was holding the object, I wouldn't be able to map
that back to one of my .NET threads.
 
If it is locking the same resource, it will definitely cause a problem. :-)

The architecture for multi-threaded apps is far more complex than it seems
on the surface. I like Jon's suggestions on this one. There was also an MSDN
article a few months ago on locking strategies. If I can find it, and have
time, I will post an URL.

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

*********************************************
Think outside the box!
*********************************************
 
Maybe I'm just misunderstanding what you're saying here.

Two threads A and B.

Thread A executes the code

lock(_Resource)
{
...
}

and is executing the code ...

Before Thread A exits the previously defined scope, Thread B attempts
to execute the code

lock(_Resource)
{
...
}

You're saying the app is coded incorrectly and will generate a
deadlock? If so, what is the point of the lock statement? Thread B
should wait until Thread A exits its block, then Thread B will enter
the block automatically.
 
Back
Top