I have a class instance that is used by several other classes in other threads to communicate.
This class uses a slim reader/writer lock (WinAPI's SRWLOCK
) as a synchronization object and a couple of RAII helper classes to actually lock/unlock the thing:
static unsigned int readCounter = 0;
class CReadLock
{
public:
CReadLock(SRWLOCK& Lock) : m_Lock(Lock) { InterlockedIncrement(&readCounter); AcquireSRWLockShared(&m_Lock); }
~CReadLock() {ReleaseSRWLockShared(m_Lock); InterlockedDecrement(&readCounter);}
private:
SRWLOCK& m_Lock;
};
class CWriteLock
{
public:
CWriteLock(SRWLOCK& Lock) : m_Lock(Lock) { AcquireSRWLockExclusive(&m_Lock); }
~CWriteLock() { ReleaseSRWLockExclusive(&m_Lock); }
private:
SRWLOCK& m_Lock;
};
The problem is the whole thing deadlocks all the time. When I pause the deadlocked program, I see:
AcquireSRWLockExclusive()
;AcquireSRWLockShared()
;readCounter
global is set to 3.The way I see it, the only way for this to happen is CReadLock
instance's destructor hasn't been called somehow somewhere so the lock is perpetually stuck. However, the only way for this to happen (as far as I know) is because an exception has been thrown. It wasn't. I checked.
What might be the problem? How should I go about fixing (or at least locating the reason of) this thing?
Are you using Read lock in recursive manner?
void foo()
{
CReadLock rl(m_lock);
...
bar();
}
void bar()
{
CReadLock rl(m_lock);
...
}
void baz()
{
CWritedLock rl(m_lock);
...
}
if foo()
and baz()
are called simultaneously you may get deadlock:
1. (Thread A) foo locks
2. (Thread B) baz asks to create write lock now all read locks would block until all are released - waits.
3. (Thread A) bar tries to lock and waits because there is pending write lock
The fact that you have 2 threads stuck on Read lock and Read Lock counter is 3 that most likely shows that you have a recursion in one of the locks - i.e. one thread had tried to acquired read lock twice.
one thread stuck in AcquireSRWLockExclusive();
two threads stuck in AcquireSRWLockShared();
readCounter global is set to 3.
Well, as far as I can read from it, you have one thread holding the read lock currently, one write thread waiting for that read lock to be released, and two read threads waiting for that write thread to get and release the lock.
In other words, you have one dangling read thread, which has not bee destructed, like you say yourself. Add debug print to destructor and constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With