I just committed to svn a small function that can be used to
help debug deadlocks that result from the incorrect use of
managed locks.

Managed locks (implemented in the Monitor class and usually
invoked with the lock () construct in C#) are subject to the
same incorrect uses of normal locks, though they can be
safely taken recursively by the same thread.

One of the obviously incorrect way to use locks is to have
multiple locks and acquire them in different orders in
different codepaths. Here is an example:

I added an explicit Sleep () call to make the race condition
happen almost every time you run such a program. The issue
with such deadlocks is that usually the race time window is
very small and it will go unnoticed during testing. The new
feature in the mono runtime is designed to help find the
issue when a process is stuck and we don't know why.

Now you can attach to the stuck process using gdb and issue
the following command:

We can see that there are three locks currently held by
three different threads. The first has been recursively
acquired 2 times. The other two are more interesting because
they each have a thread waiting on a semaphore associated
with the lock structure: they must be the ones involved in
the deadlock.

Once we know the threads that are deadlocking and the
objects that hold the lock we might have a better idea of
where exactly to look in the code for incorrect ordering of
lock statements.

In this particular case it's pretty easy since the objects
used for locking are static fields. The easy way to get the
class is to notice that the object which is locked twice
(0x2ffd8) is of the same class as the static fields: