Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it necessary to call pthread_mutex_destroy on a mutex?

I am using pthread_mutex_t in a C++ program, as follows:

class Mutex : public noncopyable
{
public:
    Mutex()
    {
        pthread_mutex_init(&m_mutex, NULL);
    }

    void acquire()
    {
        pthread_mutex_lock(&m_mutex);
    }

    void release()
    {
        pthread_mutex_unlock(&m_mutex);
    }

private:
    pthread_mutex_t m_mutex;
};

(The class is not copyable - http://www.boost.org/doc/libs/1_53_0/boost/noncopyable.hpp)

The thing that I don't understand - is it considered an error to not call pthread_mutex_destroy in the destructor? The documentation I have read does not state that destroy must be called.

Does anyone know, what does pthread_mutex_destroy actually do and under what conditions is it required?

EDIT

Does the answer for pthread_mutex_destroy also apply to pthread_cond_destroy, etc? They seem almost like useless functions to me, unless pthread_mutex_init et. al. are allocating memory? (the docs, to me, aren't entirely clear on this.)

It doesn't hurt me to call destroy anyway, so the question is largely academic.

On linux anyway, it seems destroy only sets the mutex to an invalid state:

int
__pthread_mutex_destroy (mutex)
     pthread_mutex_t *mutex;
{
  if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
      && mutex->__data.__nusers != 0)
    return EBUSY;

  /* Set to an invalid value.  */
  mutex->__data.__kind = -1;

  return 0;
}

(From glibc-2.14/nptl/pthread_mutex_destroy.c).

like image 843
Wayne Uroda Avatar asked Feb 06 '13 03:02

Wayne Uroda


3 Answers

If someone provides you with a destroy function, then you are required to call it as the final action on that object before it goes out of scope.

On architectures and implementations where the API has no effect, this will be optimised away, however if the API changes in future to require cleaning up of internal state and your code does not call it, your code will now have a memory and/or resource leak.

So the simple answer is yes; you must call this API - and here's the thing - even if the API does nothing at the moment, because although the API itself is fixed forever into the future, the implementation behind the API is not.

like image 163
SecurityMatt Avatar answered Sep 21 '22 17:09

SecurityMatt


From IEEE documentation which is the standard governing POSIX:

The pthread_mutex_destroy() function shall destroy the mutex object referenced by mutex; the mutex object becomes, in effect, uninitialized. An implementation may cause pthread_mutex_destroy() to set the object referenced by mutex to an invalid value. A destroyed mutex object can be reinitialized using pthread_mutex_init(); the results of otherwise referencing the object after it has been destroyed are undefined.

The documentation does not say you must call it. But it is a good practice to do so.
Calling this api will signal the POSIX library to release all the resources which were reserved for use of this particular mutex object during its initialization.
It is logical to assume mutex initialization does allocate/reserve some resources.

like image 27
Alok Save Avatar answered Sep 18 '22 17:09

Alok Save


A few years have gone by and @SecurityMatt was right. To settle the debate, you must call pthread_mutex_destroy to satisfy API requirements and to potentially free memory.

Here is an excerpt of the latest pthread_mutex_destroy:

int _pthread_mutex_destroy (pthread_mutex_t *mutex)
{
  if (mutex->__attr == __PTHREAD_ERRORCHECK_MUTEXATTR
      || mutex->__attr == __PTHREAD_RECURSIVE_MUTEXATTR)
    /* Static attributes.  */
    ;
  else
    free (mutex->__attr);

  return 0;
}
like image 23
tothphu Avatar answered Sep 20 '22 17:09

tothphu