Commit 24415ced authored by Kenton Varda's avatar Kenton Varda

Apparently read locks are not recursive on BSD/OSX. Adjust test so that it doesn't deadlock.

parent 02386c72
......@@ -57,11 +57,28 @@ TEST(Mutex, MutexGuarded) {
{
auto rlock1 = value.lockShared();
{
auto rlock2 = value.lockShared();
EXPECT_EQ(789, *rlock2);
auto rlock3 = value.lockShared();
EXPECT_EQ(789, *rlock3);
auto rlock4 = value.lockShared();
EXPECT_EQ(789, *rlock4);
}
Thread thread2([&]() {
Locked<uint> threadLock = value.lockExclusive();
*threadLock = 321;
});
#if KJ_USE_FUTEX
// So, it turns out that pthread_rwlock on BSD "prioritizes" readers over writers. The result
// is that if one thread tries to take multiple read locks, but another thread happens to
// request a write lock it between, you get a deadlock. This seems to contradict the man pages
// and common sense, but this is how it is. The futex-based implementation doesn't currently
// have this problem because it does not prioritize writers. Perhaps it will in the future,
// but we'll leave this test here until then to make sure we notice the change.
delay();
EXPECT_EQ(789, *rlock1);
......@@ -73,6 +90,7 @@ TEST(Mutex, MutexGuarded) {
auto rlock4 = value.lockShared();
EXPECT_EQ(789, *rlock4);
}
#endif
delay();
EXPECT_EQ(789, *rlock1);
......
......@@ -174,7 +174,14 @@ class MutexGuarded {
// An object of type T, guarded by a mutex. In order to access the object, you must lock it.
//
// Write locks are not "recursive" -- trying to lock again in a thread that already holds a lock
// will deadlock. If you think you need recursive locks, you are wrong. Get over it.
// will deadlock. Recursive write locks are usually a sign of bad design.
//
// Unfortunately, **READ LOCKS ARE NOT RECURSIVE** either. Common sense says they should be.
// But on many operating systems (BSD, OSX), recursively read-locking a pthread_rwlock is
// actually unsafe. The problem is that writers are "prioritized" over readers, so a read lock
// request will block if any write lock requests are outstanding. So, if thread A takes a read
// lock, thread B requests a write lock (and starts waiting), and then thread A tries to take
// another read lock recursively, the result is deadlock.
public:
template <typename... Params>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment