Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What could cause a deadlock of a single write/multiple read lock?

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:

  • one thread stuck in AcquireSRWLockExclusive();
  • two threads stuck in 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?

like image 674
obamator Avatar asked Oct 25 '12 08:10

obamator


2 Answers

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.

like image 132
Artyom Avatar answered Nov 14 '22 23:11

Artyom


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.

like image 26
hyde Avatar answered Nov 14 '22 23:11

hyde