.NET Deadlock Detection with PostSharp
SharpCrafters, makers of the AOP framework PostSharp, have developed a drop-in deadlock detection toolkit. This toolkit works with most standard locking primitives such as Mutex, Monitor, and ReaderWriterLock with only a single line of code added to the project.
When a thread waits for a lock for more than 200ms, the toolkit will run a deadlock detection routine. If it detects a deadlock, it will throw DeadlockException in all threads that are part of the deadlock. The exception gives a detailed report of all threads and all locks involved in the deadlock, so you can analyze the issue and fix it.
Deadlock detection isn’t exactly hard, but requires a significant amount of boilerplate code to be meticulously applied across the application. The PostSharp Threading Toolkit automatically injects this code around lock statements using IL rewriting techniques.
It should be noted that this uses very conservative logic to prevent false positives; they consider erroneously throwing a DeadlockException to be worse than an undetected deadlock. Also, it won’t work at all on asymmetric locks such as ManualResetEvent, AutoResetEvent, Semaphore and Barrier because “not clear which thread is responsible for ‘signaling’ or ‘releasing’ the synchronization resource”.
Locks it can handle include:
- Mutex: WaitOne, WaitAll, Release
- Monitor: Enter, Exit, TryEnter, TryExit (including c# lock keyword; Pulse and Wait methods are not supported)
- ReaderWriterLock: AcquireReaderLock, AcquireWriterLock, ReleaseReaderLock, ReleaseWriterLock, UpgradeToWriterLock, DowngradeToReaderLock (ReleaseLock, RestoreLock not supported)
- ReaderWriterLockSlim: EnterReadLock, TryEnterReadLock, EnterUpgradeableReadLock, TryEnterUpgradeableReadLock, EnterWriteLock, TryEnterWriteLock, ExitReadLock, ExitUpgradeableReadLock, ExitWriteLock,
- Thread: Join
The PostSharp Threading Toolkit is released under the BSD 2-Clause License and is available on GitHub.