PTHREAD_MUTEXATTR_GETROBUST_NP(3)
π pthread_mutexattr_getrobust(3) β Library Functions Manual π
okay bestie, sit down, hydrate, and let's talk about robust mutexes because this one is genuinely so cool and also carries a lot of responsibility β¨
πΈ NAME πΈ
pthread_mutexattr_getrobust, pthread_mutexattr_setrobust β get and set the robustness attribute of a mutex attributes object
π LIBRARY π
POSIX threads library (libpthread, -lpthread)
π¦ SYNOPSIS π¦
#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
π DESCRIPTION π
So pthread_mutexattr_getrobust() takes the value of the robustness attribute of the mutex attributes object that attr points at, and parks it in *robustness. Simple. Iconic.
And pthread_mutexattr_setrobust() sets that same robustness attribute on the object attr points at, to whatever you passed in *robustness. (yes, the manpage really writes *robustness there, we're not fighting it π)
The robustness attribute is literally the vibe check on what a mutex does when its owning thread dies without unlocking it. Unhinged behavior, honestly. Here are the valid values for robustness:
PTHREAD_MUTEX_STALLEDβ this is the default for a mutex attributes object. If a mutex gets initialized with thePTHREAD_MUTEX_STALLEDattribute and its owner dies without unlocking it, the mutex stays locked forever afterwards, and every future attempt to callpthread_mutex_lock(3)on that mutex will block indefinitely. Yeah. Forever. Not dramatic, just facts. πPTHREAD_MUTEX_ROBUSTβ if a mutex is initialized with thePTHREAD_MUTEX_ROBUSTattribute and its owner dies without unlocking it, then any future attempt to callpthread_mutex_lock(3)on this mutex will succeed and returnEOWNERDEAD, which is the "hey the original owner doesn't exist anymore and this mutex is in an inconsistent state" notification. Usually, after you getEOWNERDEADback, the next owner should callpthread_mutex_consistent(3)on the acquired mutex to make it consistent again before using it any further. Slay responsibly.
Now, if the next owner unlocks the mutex using pthread_mutex_unlock(3) before making it consistent, the mutex becomes permanently unusable, and any subsequent attempts to lock it using pthread_mutex_lock(3) will fail with the error ENOTRECOVERABLE. For real. The only permitted operation on a mutex in that state is pthread_mutex_destroy(3). That's it. That's the whole guest list.
And if the next owner terminates before calling pthread_mutex_consistent(3), further pthread_mutex_lock(3) operations on this mutex will still return EOWNERDEAD.
π«Ά Also important: theattrargument ofpthread_mutexattr_getrobust()andpthread_mutexattr_setrobust()should refer to a mutex attributes object that was initialized bypthread_mutexattr_init(3). Otherwise the behavior is undefined. Do not freestyle this one, bestie.
β RETURN VALUE β
On success, these functions return 0. On error, they return a positive error number.
In the glibc implementation, pthread_mutexattr_getrobust() always returns zero. Every time. Always. π
π ERRORS π
EINVALβ a value other thanPTHREAD_MUTEX_STALLEDorPTHREAD_MUTEX_ROBUSTwas passed topthread_mutexattr_setrobust().
π VERSIONS π
In the Linux implementation, when you're using process-shared robust mutexes, a waiting thread also receives the EOWNERDEAD notification if the owner of a robust mutex performs an execve(2) without first unlocking the mutex. POSIX.1 does not specify this little detail, but the same behavior also occurs in at least some other implementations. So it's giving "unofficial but widely agreed upon" energy β¨
π STANDARDS π
POSIX.1-2008. We stay standards-compliant. Periodt.
πΈ HISTORY πΈ
glibc 2.12. POSIX.1-2008.
Okay so here's the lore π« β before pthread_mutexattr_getrobust() and pthread_mutexattr_setrobust() got added 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);
And correspondingly, the constants PTHREAD_MUTEX_STALLED_NP and PTHREAD_MUTEX_ROBUST_NP were also defined.
These GNU-specific APIs first appeared in glibc 2.4, and nowadays they're obsolete and should not be used in new programs. Since glibc 2.34 these APIs are marked as deprecated. So likeβ¦ respectfully, retire them. π
π EXAMPLES π
The program below demonstrates the use of the robustness attribute of a mutex attributes object. In this program, a thread holding the mutex dies prematurely without unlocking the mutex. The main thread subsequently acquires the mutex successfully and gets the error EOWNERDEAD, after which it makes the mutex consistent.
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
π¦ Program source π¦
#include <err.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
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)
errc(EXIT_FAILURE, s, "pthread_mutex_consistent");
printf("[main] Mutex is now consistent; unlocking\n");
s = pthread_mutex_unlock(&mtx);
if (s != 0)
errc(EXIT_FAILURE, 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");
errc(EXIT_FAILURE, s, "pthread_mutex_lock");
}
}
π SEE ALSO π
get_robust_list(2)set_robust_list(2)pthread_mutex_consistent(3)pthread_mutex_init(3)pthread_mutex_lock(3)pthreads(7)
and that's the whole page, bestie!! πβ¨ this one came from Linux man-pages 6.20, dated 2026-02-08, and you can find it filed under pthread_mu...r_setrobust(3) in the Library Functions Manual. go make your mutexes robust, and please, for the love of everything, call pthread_mutex_consistent(3) before you unlock. mwah π«ΆππΈ
π¦ where this page comes from
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- π the page's license: Linux-man-pages-copyleft
- Copyright 2017, Yubin Ruan <ablacktshirt@gmail.com>
- Copyright 2017, Michael Kerrisk <mtk.manpages@gmail.com>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms