Pthread Mutex Assertion Error

Pthread mutex assertion error

Rock solid for 4 days straight. I'm declaring victory on this one. The answer is "stupid user error" (see comments above). A mutex should only be unlocked by the thread that locked it. Thanks for bearing with me.

Pthread mutex lock assertion fails

This usually indicates that the lock has become corrupted in some way. One possibility is that you are trying to lock a lock that was never initialized or has already been destroyed and not re-initialized. Another possibility is that some other piece of code is stomping on the mutex, possibly by accessing an array out of bounds or by accessing some memory after it has been freed.

pthread_mutex_lock_full assertion failed error

In GLIBC 2.31, you were running the following source code of pthread_mutex_lock():

    oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
newval, 0);

if (oldval != 0)
{
/* The mutex is locked. The kernel will now take care of
everything. */
int private = (robust
? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
: PTHREAD_MUTEX_PSHARED (mutex));
int e = futex_lock_pi ((unsigned int *) &mutex->__data.__lock,
NULL, private);
if (e == ESRCH || e == EDEADLK)
{
assert (e != EDEADLK
|| (kind != PTHREAD_MUTEX_ERRORCHECK_NP
&& kind != PTHREAD_MUTEX_RECURSIVE_NP));
/* ESRCH can happen only for non-robust PI mutexes where
the owner of the lock died. */
assert (e != ESRCH || !robust);

/* Delay the thread indefinitely. */
while (1)
lll_timedwait (&(int){0}, 0, 0 /* ignored */, NULL,
private);
}

oldval = mutex->__data.__lock;

assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
}

In the above code, the current value of the mutex is atomically read and it appears that it is different than 0 meaning that the mutex is locked.
Then, the assert is triggered because the owner of the mutex died and the mutex was not a robust one (meaning that the mutex has not been automatically released upon the end of the owner thread).

If you can modify the source code, you may need to add the "robust" attribute to the mutex (pthread_mutexattr_setrobust()) in order to make the system release it automatically when the owner dies. But it is error prone as the corresponding critical section of code may have not reached a sane point and so may leave some un-achieved work...

So, it would be better to find the reason why a thread may die without unlocking the mutex. Either it is an error, either you forgot to release the mutex in the termination branch.

Mutex assertion error with non-zero heap

OK, the solution is silly. I simply didn't initialize the mutex. The reason I didn't think of this was that the above code worked fine with calloc(). I guess omitting initialization will backfire when you least expect it.

From manpages:

The pthread_mutex_init() function shall initialize the mutex
referenced by mutex with attributes specified by attr. If attr is
NULL, the default mutex attributes are used; the effect shall be the
same as passing the address of a default mutex attributes object. Upon
successful initialization, the state of the mutex becomes initialized
and unlocked.

So in this case:

int main(){
nonzero_heap();
pthread_mutex_t* mutex = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutex, NULL); # NEW LINE
pthread_mutex_lock(mutex);
return 0;
}

boost::mutex::~mutex(): Assertion `!pthread_mutex_destroy(&m)' failed

Do Not inherit from boost::mutex, the boost::mutex class does not have a virtual destructor, so it is not actually meant for Inheritance.

Possible Root Cause:

The error you are getting indicates that you are calling unlock on a mutex that was never locked. Something like:

boost::mutex m;   
m.unlock();

By trying to do lock and unlock, it seems you lose the track of whether the mutex as locked.This is very often the problem when you perform resource management manually. C++ allows a specific mechansim called Resource Allocation is Initilization(RAII) for safe guarding against such problems.

Suggestted Solution:

You should use RAII, rather than unlocking the mutex explicitly. You could use the boost::mutex::scoped_lock to implement RAII:

struct YourStruct
{
void doSomething()
{
boost::mutex::scoped_lock l(m_mutex);
//do something Interesting
}
private:
boost::mutex m_mutex;
};

Why am I receiving a lock assertion failure for a simple boost producer/consumer program?

If you have the lock owned by a lock guard (scoped_lock) it's an error to manually manipulate the lock.

If you must manipulate the lock before the end of the scope, you can do so on the scoped_lock itself:

lock.unlock();  // instead of buffer_lock -> unlock();


Related Topics



Leave a reply



Submit