1
votes

Faced with intermittent multithreading error that appears as application hang. When I pause debugging I see that thread waits on lock(_sync) clause. So the questions are:

  1. Is it the only reason to wait on lock when some other thread locked the object?
  2. How to know what thread(s) holding a lock of particular object (during debugging or run-time)?

I believe it is not a "deadlock" because deadlock implies presence of at least two object and two threads, while there is only one synchronization object in considering code. I think that some other thread locked the object and hanged but I cant find which thread it is.

2
If your app hangs with 0% CPU then you have deadlock with prob>0.999. If it hangs with 100% CPU then you have unterminated busy loop.David Heffernan
Well, not necessarily. If the app hangs with 0% CPU then the thread holding the lock might just be blocked on I/O, for example. The only thing you can say with any reasonable amount of certainty is that 100% CPU probably means an infinite loop. 0% CPU can have many explanations that don't involve deadlocks.cdhowie
@cdhowie I'm assuming that eventually the IO will complete.David Heffernan
Perhaps, it depends. Maybe the I/O is on a serial port, and the device at the other end isn't sending any data. Maybe it's I/O against a TCP socket where the remote endpoint isn't sending any data (or the connection was lost without a FIN being received).cdhowie
@cdhowie that's the prob<1-0.999David Heffernan

2 Answers

4
votes

I'll document some essential debugging techniques. Start with Debug + Windows + Threads, it shows you a list of all threads that are running in your process. You can hover over the Location column and you'll get a tooltip that shows the stack trace for the thread. That lets you quickly home in on threads that actually are running your code. Double click one of interest, then switch to Debug + Windows + Call Stack to get a more permanent view. This may help you find the thread that has acquired the lock.

Failing that, you can find out what thread owns the lock object. Switch to the thread that is blocked by double-clicking it then use Debug + Windows + Memory + Memory 1. Type "_sync" in the Address box. Right-click the window and select "4-byte Integer". Subtract 4 from the hexadecimal address shown in the upper left corner of the window and type that address in the Address box. Or click the scrollbar up arrow and look at the last value in the first line. That's the Thread.ManagedThreadId of the thread that owns the lock. Beware that this doesn't always work, this field in an object is used for other purposes as well (GetHashCode for example).

Knowing the managed ID of the thread now lets you look in the Debug + Windows + Threads window for the thread. But only on VS2010, earlier versions don't display the managed ID of threads in this window. For those, you'll need to add some tracing code that displays the value of Thread.CurrentThread.ManagedThreadId. Adding tracing code is in general a useful technique to troubleshoot threading problems. It is very risky however, this code alters the timing and may make the threading problem disappear. Many trace listeners also have an implied lock.

0
votes

one way to debug this (without the nice shiny VS2010 fetures) would be to make the access to the _sync only possible with a property/accessor. There put some diagnostic-text or breakpoints and you can see what thread want's the sync and when.

Other than this I cannot give any reasonable answer without seeing code.