This looks like a bug in the framework (tested on v3.5 and v4.0). The ExitReadLock()
should throw a SynchronizationLockException
, but doesn't in this case. Indeed, you can trigger a very similar issue much more simply with the following:
rwlock.EnterReadLock();
rwlock.ExitReadLock();
// This should throw a SynchronizationLockException but doesn't
rwlock.ExitReadLock();
// At this point, rwlock.CurrentReaderCount = 0x0fffffff
(In fact, ExitReadLock()
will corrupt the lock if it's called without a matching EnterReadLock()
on any thread that has previously entered the lock.)
The issue only occurs when the ReaderWriterLockSlim
is created using the parameterless constructor, or with LockRecursionPolicy.NoRecursion
. If created with LockRecursionPolicy.SupportsRecursion
, it will not be corrupted by the unmatched ExitReadLock()
.
If you expect the reader thread to be interrupted whilst waiting for entry into lock, I would suggest changing the reader thread method to:
var reader = new Thread(() =>
{
var entered = false;
try
{
rwlock.EnterReadLock();
entered = true;
s_logger.Info("Enter");
}
finally
{
if (entered) rwlock.ExitReadLock();
}
});