I've been working on a small sand-boxed example to help me figure out how to use rwlocks. Everything seems fairly straightforward, however I'm getting deadlocks in my example every once and a while and don't understand why it's happening.
I've put the code example on pastebin because it's more than a few lines of code: http://pastebin.org/359203
If you run the example. When it eventually deadlocks the last three print statements will be one of two cases:
one:
th4: request lock
th3: request lock
th4: locked
two:
th3: request lock
th4: request lock
th3: locked
Based on the output. To me it seems like there is an eventual deadlock from a second call to a locking function, whether it's to a read lock, or a write lock. But since one of the threads has the lock, and the same thread is what calls the second locking function, why is it deadlocking? Even more interesting, what is it in this small case that is causing the deadlock?
Note that I'm on Mac OS X, and that this is a seriously contrived example. It's sand-boxed from something else I'm working on and wanted to make sure I get this part right.
I posted a workaround for this question in Pthread RWLock on MAC Deadlocking but not on Linux?
It is platform independent, and the general method ought to allow for other tricks like upgrading from read to write, etc.
Your problem is that
pthread_rwlock_wrlock(3)
is not reentrant. The documentation clearly states that the results of calling this method when the thread already holds the lock are undefined. Your code specifically calls the method twice without releasing the lock in between.pthread_rwlock supports recursive read locking, but not recursive write locking. If you write lock the lock while you already hold it, you have entered the realm of undefined behavior. This is the case for your
thfn3()
.It's clearer if you call the threads the "reader" (thfn4) and the "writer" (thfn3). Case one is then:
In this case, the reader is likely unable to lock again because there is a writer waiting on the lock, and would-be writers block would-be readers.
Case two is:
This case can likely only be explained by appeal to details of the rwlock implementation.
See the bug I reported with apple. This is the problem.
https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/7/wo/0blX77DJS8lBTTxVnTsNDM/5.83.28.0.13
Here's the open radar bug.
http://openradar.appspot.com/8588290