3

classical question please; I didn't find confirmation from code; C language. I'm running the below code on Windows.

/* This is an implementation of the threads API of POSIX 1003.1-2001.*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
//equivalent to PTHREAD_MUTEX_ERRORCHECK

void* thread_function(void *args)
{
    int rc;
    rc = pthread_mutex_unlock( & mutex );
    printf( "[thread_function] pthread_mutex_unlock rc: %d \n", rc);
    return 0;
}

int main(int argc, char* argv[])
{
    int rc;
    pthread_t id;

    pthread_mutex_lock( &mutex );
    rc =  pthread_create(&id, NULL, thread_function, NULL);
    pthread_join(id, NULL);

    printf( "[main] completed\n");
}

rc = pthread_mutex_unlock( & mutex ); - returns rc equal to 1 which is as expected.

but when I change the code to rc = pthread_mutex_lock( & mutex ); - the error does not occur. But in many Pthread API doc it is mentioned that: "If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then error checking shall be provided. If a thread attempts to relock a mutex that it has already locked, an error shall be returned."

But it is not returned for me, and the question why? The only guess I have - it depends on PThread realization which I'm using. And it also may depend on OS; i.e. same code and the same version of Pthread lib will give different result on Linux.

Can anyone please clarify?

Thanks!

BayE
  • 75
  • 2
  • 6
  • Why would you expect `pthread_mutex_lock(&mutex);` to return an error? It is a valid call, at least in the context you show. – alk Jan 27 '18 at 11:56

3 Answers3

2

When a thread tries to lock a mutex locked by another thread, it blocks. This is of course the whole point: it would be useless if it were an error. The error checking is for programs where a thread might try to lock a mutex it has already locked. That usually results from a logic bug, although one could simulate a recursive mutex with it or perhaps use the locked state of the mutex as some sort of memory.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
0

Generally, when you tried to lock mutex(Default Type) second time in the same thread your code has been blocked. To prevent this blocking situation, error checking mutex is used.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>

#define IN_MAIN     ""
#define IN_THREAD   "\t"
#define START_MAIN  printf(IN_MAIN "\n-- Main Start -- \n");
#define END_MAIN    printf(IN_MAIN "-- Main End -- \n\n");  \
                    exit(EXIT_SUCCESS);

#define ERROR_HANDLER(en, msg) \
                do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void * thread_routine(void * arg)
{
    printf(IN_THREAD "-- Thread Start -- \n");
    int ret;

    pthread_mutex_lock(&mutex);
    printf(IN_THREAD " Thread acquire lock for first time \n");

    ret = pthread_mutex_lock(&mutex);
    if(ret)
    {
        switch(ret)
        {
            case EDEADLK:
                printf(IN_THREAD " A deadlock condition was detected \n");
                break;

            default:
                ERROR_HANDLER(ret, "pthread_mutex_lock");
        }
    }

    sleep(1);
    ret = pthread_mutex_unlock(&mutex);
    printf(IN_THREAD " Thread release lock first time -- %d \n", ret);

    sleep(1);
    ret = pthread_mutex_unlock(&mutex);
    printf(IN_THREAD " Thread release lock second time -- %d \n", ret);
    printf(IN_THREAD "-- Thread End --\n");
    pthread_exit(NULL);
}

int main(int argc, char ** argv)
{
    START_MAIN;
    pthread_t thread_id;
    pthread_mutexattr_t mutex_attr;
    int mutex_type, ret=0;

    pthread_mutexattr_init(&mutex_attr);
    ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
    if(ret)
        ERROR_HANDLER(ret, "pthread_mutexattr_settype");

    pthread_mutex_init(&mutex, &mutex_attr);
    pthread_create(&thread_id, NULL, thread_routine, NULL);
    pthread_join(thread_id, NULL);
    END_MAIN;
}

Consider above example, when you execute the above code, it print "A deadlock condition was detected". This is because of the type of mutex is error check. Now comment the line

ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);

and execute the code. You'll notice your code is blocked after it print "Thread acquire lock for first time".

Jai Desai
  • 27
  • 6
0

One of the mistakes in the Posix spec is the notion of "default" mutex type -- which is implementation dependent. Meaning the the semantics of a "default" mutex is any ones guess. Confusing? You bet.

My advice is to never use "default" for mutex type if you care about portability at all.