Understanding QReadWriteLock and the dangers of nested locking
-
I have some trouble understanding the subtleties of QReadWriteLocks:
Consider two threads, A Producer, hence writer, B Consumer hence reader, both share a common buffer S
Lets assume two functions f1 and f2 in B lock S. Further inside f1 f2 is called, hence nested locking is possible.
Now consider the instant when f1 is executed and locks for read for the first time. If thread A gets called and wants to write he gets blocked.
Further if inside f1 f2 gets called and wants to lock it can't since a blocked writer is waiting.
Hence we get a very nasty deadlock that is non-predictable and occurs only if a writer kicks in between the lock in f1 and the call of f2.
My current approach to avoid such bugs is a debug tool that tracks locking and asserts if the same thread tries to lock for read twice, but this is quite cumbersome.
What other functionality can be used to prevent such scenarios ? Why does QReadWriteLock permit them at all ?
Are there some general rules of thumb to avoid the above scenarios in the design phase?Thanks in Advance, Martin
-
bq. Further inside f1 f2 is called, hence nested locking is possible.
Only if we have a recursive mode (QReadWriteLock::Recursive)
bq. Further if inside f1 f2 gets called and wants to lock it can’t since a blocked writer is waiting.
It is no true. The lock control is made by thread. In other words, your second attempt lock will success and no deadlock will occurs.
Despite of this explanation, we really have "a bug in QReadWriteLock::tryLockForRead()":https://bugreports.qt-project.org/browse/QTBUG-33262