5

A thread which hold mutex died. Another thread will deadlock when it calls "pthread_mutex_lock", although I use "PTHREAD_MUTEX_ERRORCHECK" attribute.

#include <pthread.h>
#include <iostream>
#include <unistd.h>

using namespace std;

pthread_mutex_t mutex;

void *handler(void *)
{
    cout << "child thread" << endl;
    int ret = pthread_mutex_lock(&mutex);
    cout << "child ret: " << ret << endl;
    pthread_exit(NULL);
}

int main()
{
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);

    pthread_mutex_init(&mutex, &attr);
    pthread_mutexattr_destroy(&attr);

    pthread_t tid;
    pthread_create(&tid, NULL, handler, NULL);

    sleep(2);
    cout << "father awake" << endl;

    int ret = pthread_mutex_lock(&mutex);
    cout << "father ret: " << ret << endl;
    return 0;
}

Output:

enter image description here

[LINUX ENVIRONMENT]: Linux ubuntu 3.19.0-25-generic #26~14.04.1-Ubuntu SMP

Pengcheng
  • 439
  • 1
  • 4
  • 14
  • You didn't ask any question here -- but if your question is "how to handle this problem", the best solution is to make sure your thread releases any mutexes it might be holding, before exiting. – Jeremy Friesner Dec 03 '15 at 02:45
  • [This](http://stackoverflow.com/q/4424193/1230086) question appears to be asking the results of what your code does. – tijko Dec 03 '15 at 04:14

2 Answers2

4

You are perhaps thinking of the robust attribute of mutexes (pthread_mutexattr_setrobust()), rather than of the errorcheck type of mutex. A robust mutex would have notified your main thread that the holder of the mutex's lock had terminated with EOWNERDEAD.

The PTHREAD_MUTEX_ERRORCHECK type, on the other hand, simply guards against three kinds of errors:

  1. attempting to recursively lock one's own locked mutex (not applicable here)
  2. attempting to unlock a mutex locked by another thread (not applicable here)
  3. attempting to unlock an unlocked mutex (not applicable here)
pilcrow
  • 56,591
  • 13
  • 94
  • 135
1

This is a small example of using the pthread_mutexattr_setrobust call to allow for setting the mutex that was never unlocked back to a consistent state:

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

pthread_mutex_t lock;

void dropped_thread(void)
{
    printf("Setting lock...\n");
    pthread_mutex_lock(&lock);
    printf("Lock set, now exiting without unlocking...\n");
    pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
    pthread_t lock_getter;
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); 
    pthread_mutex_init(&lock, &attr);
    pthread_mutexattr_destroy(&attr);
    pthread_create(&lock_getter, NULL, (void *) dropped_thread, NULL);
    sleep(2);

    printf("Inside main\n");
    printf("Attempting to acquire unlocked mutex?\n");

    pthread_mutex_consistent(&lock);
    pthread_mutex_unlock(&lock);
    pthread_mutex_lock(&lock);

    printf("Successfully acquired lock!\n");
    pthread_mutex_destroy(&lock);
    return 0;
}

As you can see by making the call to pthread_mutex_consistent after setting the mutex robustness, its state is marked as consistent again.

tijko
  • 7,599
  • 11
  • 44
  • 64
  • You forget to initialize the mutex with `pthread_mutex_init`. Without that your code will result in deadlock. – walkerlala Aug 07 '17 at 06:55