Check if pthread_mutex is initialized

10,078

No you can't detect that. EINVAL may be returned for an uninitialized mutex, but it mustn't necessarily.

In addition POSIX states:

Attempting to initialize an already initialized mutex results in undefined behavior.

so you shouldn't try that.

The best way is to avoid that situation completely and to initialize the variable properly. This should be done with the macro PTHREAD_MUTEX_INITIALIZER.

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
Share:
10,078
truschival
Author by

truschival

Updated on June 09, 2022

Comments

  • truschival
    truschival almost 2 years

    Using pthreads it mandatory to call pthread_mutex_init() on any mutex before obtaining the lock.

    According to POSIX the locking an uninitialized mutex is only defined for mutex with priority protection (opengroup : pthread_mutex_lock)

    According to the manpage pthread_mutex_lock.3thr it should return EINVAL if called on an uninitalized mutex. Assuming portability is not an issue, would it be valid (a good idea?) to write code like:

    pthread_mutex_t lock;
    
    int ret = pthread_mutex_lock(&lock);
    if (ret != 0){  
        if(ret == EINVAL){
            pthread_mutex_init(&lock, NULL);
        } else {
          /* other error */
        }
    } 
    

    Is there another way to check if a pthread_mutex has been initialized?

    The whole scenario is part of a library (by politics unfortunately not C++) and I want to avoid to the maximum wrong usage. I.e. A client may initialize the object created twice, may pass the object to other functions before properly initialize it etc.

    Currently there is an aditional flag in the object that marks if the mutex has been initialized, I was wondereing if this is really necessary.

    Looking at the expansion of the macro PTHREAD_MUTEX_INITIALIZER for static mutex initialization it just expands into a struct with all members set to 0. Can I assume that is not required to call mutex_destroy if it is no longer required, given the ressource itself is freed (sure if noone else uses it)?

    Update: Jens' answer is absolutely correct. The following program yields completely undefined behavior:

    int main(int argc, char** argv)
    {
    
    pthread_mutex_t lock;
    int ret = pthread_mutex_lock(&lock);
    if (ret != 0) {
        printf(" ERR : %d %s \n", ret, strerror(ret));
        if (ret == EINVAL) {
            pthread_mutex_init(&lock, NULL);
        }
    } else {
        printf(" ok \n");
    }
    pthread_mutex_unlock(&lock);
    return 0;
    }
    

    Sometimes it deadlocks, somtimes it prints o.k. .....

  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE almost 10 years
    PTHREAD_MUTEX_INITIALIZER works if you want a default-type mutex. For other types you may need an accompanying pthread_once_t object and pthread_once call to initialize it, unless only one thread has the capacity to access the resource at the time the mutex is created (e.g. dynamically allocated objects that are only placed in an index visible to other threads after they're initialized).
  • MikeyE
    MikeyE over 7 years
    I ran into this same issue, and I'm just curious, if PTHREAD_MUTEX_INITIALIZER can be used to initialize a default-type mutex, why is the function pthread_mutex_init() a part of the library? Is it meant for dynamically allocated mutex's?
  • Jens Gustedt
    Jens Gustedt over 7 years
    Yes, and for mutexes with non default properties.