What Is The Correct Behavior of Pthread_Mutex_Destroy When Destroying a Locked Mutex

what is the correct behavior of pthread_mutex_destroy when destroying a locked mutex

The quoted text:

Attempting to destroy a locked mutex or a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread results in undefined behavior.

Should be interpreted with the "results in undefined behavior" clause distributed over the "or" conjunction. In other words:

Attempting to destroy a locked mutex results in undefined behavior.

and

Attempting to destroy a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread results in undefined behavior.

The second version is significant, because when waiting on the condition variable, the associated mutex lock is released by the waiting thread.

How to safely and correctly destroy a mutex in Linux using pthread_mutex_destroy?

The POSIX spec for pthread_mutex_destroy() says:

It shall be safe to destroy an initialized mutex that is unlocked.

Which means that if thread B calls pthread_mutex_unlock() in the else clause of the if statement in foo_rele() then it's safe for thread A to call pthread_mutex_destroy() because it can only have gotten there after thread B's pthread_mutex_unlock() call has unlocked the mutex.

All of this is assuming that the reference counting is correct, such that some other thread cannot increment the count from 0 -> 1 after thread A has unlocked the mutex. In other words, at the point where the refcount drops to 0, there can't be another thread that might possibly call foo_hold().

APUE mentions this in the explanation right after the example code:

In this example, we have ignored how threads find an object before calling foo_hold. Even though the reference count is zero, it would be a mistake for foo_rele to free the object’s memory if another thread is blocked on the mutex in a call to foo_hold. We can avoid this problem by ensuring that the object can’t be found before freeing its memory. We’ll see how to do this in the examples that follow.

How to properly dispose of a pthread mutex?

My question is, what is the best way to handle the destruction of a mutex? Should I wait for it to be free?

You should not destroy resources while they are being used because that often leads to undefined behaviour.

The correct course of action is:

  • Tell the other thread to release the resources and wait till it does, or
  • Tell the other thread to terminate politely an wait till it has done so, or
  • Pass the ownership of the resource to another thread and let it manage the resource's lifetime as it pleases, or
  • Use shared resources, so that they stay alive while its users are still around.

How to check whether a mutex lock have been destroyed or not?

Once you destroy a a c object, the data left behind is garbage. c++ doesn't let you do this. (It does but you have to explicitly ask for it.) But you are using a c library, so you have to do everything yourself.

So you have a few options:

  • use std::mutex which works nicely with c++. But as such, you mutex will have the same lifetime as your containing class. (which is neates)

  • only use pthread_mutex_destroy in your destructor. Same result as above. You mutex is destroyed as you object is destroyed, which happens exactly once.

  • use an std::optional to shield the mutex data if it is not initialized.
    Wouldn't recommend, as it is an ugly mix of c and c++.

  • use a bool to keep track whether you mutex is inited.
    This is also tricky and ugly as it is prone to mistakes.

I cannot be more specific because i don't know the rest of the code.

Destruction of pthread mutexes and deinitialization order in C++

Since initializing with PTHREAD_MUTEX_INITIALIZER is equivalent to calling pthread_mutex_init, it is OK to call pthread_mutex_destroy to destroy such a mutex.

However, calling pthread_mutex_destroy is not required; the resources will be reclaimed by the OS at program exit. Since it is an object with a trivial destructor, it is not destroyed as part of static cleanup at program exit, and so is safe to use until the end of the program.



Related Topics



Leave a reply



Submit