#include <pthread.h> int pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robustness); int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robustness);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
pthread_mutexattr_getrobust(), pthread_mutexattr_setrobust():
_POSIX_C_SOURCE >= 200809L
The robustness attribute specifies the behavior of the mutex when the owning thread dies without unlocking the mutex. The following values are valid for robustness:
Note that the attr argument of pthread_mutexattr_getrobust() and pthread_mutexattr_setrobust() should refer to a mutex attributes object that was initialized by pthread_mutexattr_init(3), otherwise the behavior is undefined.
In the glibc implementation, pthread_mutexattr_getrobust() always return zero.
Before the addition of pthread_mutexattr_getrobust() and pthread_mutexattr_setrobust() to POSIX, glibc defined the following equivalent nonstandard functions if _GNU_SOURCE was defined:
[[deprecated]] int pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr, int *robustness); [[deprecated]] int pthread_mutexattr_setrobust_np(const pthread_mutexattr_t *attr, int robustness);
Correspondingly, the constants PTHREAD_MUTEX_STALLED_NP and PTHREAD_MUTEX_ROBUST_NP were also defined.
These GNU-specific APIs, which first appeared in glibc 2.4, are nowadays obsolete and should not be used in new programs; since glibc 2.34 these APIs are marked as deprecated.
The following shell session shows what we see when running this program:
$ ./a.out [original owner] Setting lock... [original owner] Locked. Now exiting without unlocking. [main] Attempting to lock the robust mutex. [main] pthread_mutex_lock() returned EOWNERDEAD [main] Now make the mutex consistent [main] Mutex is now consistent; unlocking
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static pthread_mutex_t mtx;
static void *
original_owner_thread(void *ptr)
{
printf("[original owner] Setting lock...\n");
pthread_mutex_lock(&mtx);
printf("[original owner] Locked. Now exiting without unlocking.\n");
pthread_exit(NULL);
}
int
main(void)
{
pthread_t thr;
pthread_mutexattr_t attr;
int s;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
pthread_mutex_init(&mtx, &attr);
pthread_create(&thr, NULL, original_owner_thread, NULL);
sleep(2);
/* "original_owner_thread" should have exited by now. */
printf("[main] Attempting to lock the robust mutex.\n");
s = pthread_mutex_lock(&mtx);
if (s == EOWNERDEAD) {
printf("[main] pthread_mutex_lock() returned EOWNERDEAD\n");
printf("[main] Now make the mutex consistent\n");
s = pthread_mutex_consistent(&mtx);
if (s != 0)
handle_error_en(s, "pthread_mutex_consistent");
printf("[main] Mutex is now consistent; unlocking\n");
s = pthread_mutex_unlock(&mtx);
if (s != 0)
handle_error_en(s, "pthread_mutex_unlock");
exit(EXIT_SUCCESS);
} else if (s == 0) {
printf("[main] pthread_mutex_lock() unexpectedly succeeded\n");
exit(EXIT_FAILURE);
} else {
printf("[main] pthread_mutex_lock() unexpectedly failed\n");
handle_error_en(s, "pthread_mutex_lock");
}
}