I have a process where main initializes a mutex calling:
MutexInit( pthread_mutex_t *Mutex )
{
pthread_mutexattr_t mattr;
pthread_mutexattr_init(&mattr);
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK_NP);
#ifndef _POSIX_THREAD_PROCESS_SHARED
#error "This platform does not support process shared mutex!"
#else
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
#endif
pthread_mutex_init( Mutex, &mattr );
}
main
is initially locking mutex M1 and creates then threads T1 and T2.
T1 is started and does some work. T2 is started and does something else and at some point doing a lock on that mutex M1. Since mutex type is PTHREAD_MUTEX_ERRORCHECK_NP T2 is not blocked, instead error EDEADLK is returned, indicating that the mutex M1 is already locked. So T2 continues trying to lock. That's fine so far.
Then T1 comes to the point where it unlocks M1, but error EPERM is returned, saying, that T1 does not own the mutex !? So T2 never gets unlocked.
If I remove setting the attributes from MutexInit
:
pthread_mutexattr_init(&mattr);
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK_NP);
#ifndef _POSIX_THREAD_PROCESS_SHARED
#error "This platform does not support process shared mutex!"
#else
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
#endif
and calling pthread_mutex_init( Mutex, NULL );
, ie. default attributes, everything is working fine !
I do need the initial MutexInit
routine, because we're also using mutexes over processes (via shared memory).
Does anybody have any idea ? I've read so many articles and posts, so any help will be appriciated.
EDIT: Using a modified version of Paolo's code to demonstrate my observation:
This a the modified version of Paolo's code to fit "my sequencing":
#include <stddef.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <semaphore.h>
pthread_mutex_t m;
sem_t s1, s2;
void print(const char *s, int err)
{
printf("%s %d %s\n", s, err, strerror(err));
}
void *start_t1(void *arg)
{
sem_wait(&s1); // <-t2
print("t1: unlock ", pthread_mutex_unlock(&m));
sem_post(&s2); //->t2
}
void *start_t2(void *arg)
{
sem_wait(&s2); // <-main
print("t2: lock ", pthread_mutex_lock(&m));
sem_post(&s1); // ->t1
sem_wait(&s2); // <-t1
sem_post(&s1); // ->main
}
void main(void)
{
pthread_mutexattr_t mattr;
pthread_mutexattr_init(&mattr);
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
sem_init(&s1, 0, 0);
sem_init(&s2, 0, 0);
print("main init", pthread_mutex_init(&m, &mattr));
pthread_t t2, t1;
pthread_create(&t1, NULL, start_t1, NULL);
pthread_create(&t2, NULL, start_t2, NULL);
sem_post(&s2); // ->t2
sem_wait(&s1); // <-t2
pthread_join(t1, NULL);
pthread_join(t2, NULL);
}
The output is:
main init 0 Success
t2: lock 0 Success
t1: unlock 1 Operation not permitted
I would expect T1 to be allowed to unlock the mutex because of type PTHREAD_PROCESS_SHARED
. Am I wrong ?
If the mutex initialization is changed to defaults (pthread_mutex_init(&m, **NULL**)
), then it's working.
main init 0 Success
t2: lock 0 Success
t1: unlock 0 Success
Seems to be some kind of inverted logic !