Details
-
Task
-
Resolution: Unresolved
-
Major - P3
-
None
-
None
Description
Motivation
The mutex_is_locked is a debug test assertion to enforce the expectation that a mutex is locked in functions that expect callers to lock. It is only enabled in tests on Linux when -DENABLE_DEBUG_ASSERTIONS=ON is configured.
It breaks down in the case where:
- Thread T1 locks L
- Thread T1 waits on a condition variable CV with lock L
- While T1 is waiting, thread T2 locks and unlocks L
- T1 wakes up, and does hold the lock L, but mutex_is_locked returns false.
Scope
To keep mutex_is_locked working correctly, the condition variable functions mongoc_cond_wait and mongoc_cond_timedwait should be overridden to work with the debug form of bson_mutex_t.
Repro
The following is a test written to show the bug:
#include "mongoc/mongoc-thread-private.h"
|
|
|
#include "TestSuite.h"
|
#include "test-libmongoc.h"
|
|
|
/* Locks and unlocks the passed mutex */
|
BSON_THREAD_FUN (locker_fn, arg)
|
{
|
bson_mutex_t *lock = (bson_mutex_t *) arg;
|
/* Wait 10ms. */
|
_mongoc_usleep (10 * 1000);
|
bson_mutex_lock (lock);
|
bson_mutex_unlock (lock);
|
return NULL;
|
}
|
|
|
/* Test the mutex_is_locked assertion when a mutex is locked/unlocked by another
|
* thread while waiting for a condition variable.
|
*
|
* This requires compiling on Linux and configuring cmake with
|
* -DENABLE_DEBUG_ASSERTIONS
|
*/
|
static void
|
test_mutex_assertion (void *unused)
|
{
|
bson_mutex_t mutex;
|
mongoc_cond_t cond;
|
bson_thread_t locker_thread;
|
|
|
bson_mutex_init (&mutex);
|
mongoc_cond_init (&cond);
|
|
|
COMMON_PREFIX (thread_create) (&locker_thread, locker_fn, &mutex);
|
int r = mongoc_cond_timedwait (&cond, &mutex, 100);
|
COMMON_PREFIX (thread_join) (locker_thread);
|
BSON_ASSERT (r == ETIMEDOUT);
|
BSON_ASSERT (COMMON_PREFIX (mutex_is_locked (&mutex))); /* Fails */
|
bson_mutex_unlock (&mutex);
|
|
|
mongoc_cond_destroy (&cond);
|
bson_mutex_destroy (&mutex);
|
}
|
|
|
|
|
void
|
test_thread_install (TestSuite *suite)
|
{
|
TestSuite_AddFull (suite,
|
"/Thread/mutex_assertion",
|
test_mutex_assertion,
|
NULL /* dtor */,
|
NULL /* ctx */,
|
NULL);
|
}
|