Check if pthread_mutex is initialized
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;
truschival
Updated on June 09, 2022Comments
-
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 almost 10 years
PTHREAD_MUTEX_INITIALIZER
works if you want a default-type mutex. For other types you may need an accompanyingpthread_once_t
object andpthread_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 over 7 yearsI 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 functionpthread_mutex_init()
a part of the library? Is it meant for dynamically allocated mutex's? -
Jens Gustedt over 7 yearsYes, and for mutexes with non default properties.