Search code examples
attributespthreadsmutexshared

mutex attribute PTHREAD_PROCESS_SHARED inverts logic?


This is a follow-on to my previous question (pthread mutex (un)locking over different threads). I got puzzled by how to handle questions and answers here, so I give it a new try :o)

I'm trying to handle mutex through processes and threads and using the mutex attribute PTHREAD_PROCESS_SHARED to arrange this. I'Ve added a small example (based on Paolo's example from my previoous post) which is demonstrating my problem:

#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

T1 is not permitted to unlock the mutex initialized in main and locked by T2. Which is not what I expect! T1 should be allowed to unlock the mutex because of type PTHREAD_PROCESS_SHARED. Am I wrong ?

If the mutex initialization is changed to using default attributes (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 !


Solution

  • It is never allowed for a thread to unlock a pthreads mutex which it did not lock. For the case of error-checking mutexes, an error is returned in this case; in the case of default and normal mutexes, the behaviour is undefined.

    The purpose of PTHREAD_PROCESS_SHARED is to allow the mutex to be used to synchronise threads in different processes.