Package: libc6
Version: 2.41-12+deb13u3
Severity: normal
A standalone pthread reproducer shows unexpected behavior for a mutex
configured with PTHREAD_MUTEX_RECURSIVE and PTHREAD_MUTEX_ROBUST.
An owner thread exits while holding the mutex. The next thread receives
EOWNERDEAD and unlocks without calling pthread_mutex_consistent().
The mutex should then remain permanently unrecoverable.
Expected:
Both subsequent pthread_mutex_trylock() calls return ENOTRECOVERABLE.
Observed:
The first returns ENOTRECOVERABLE (131), but the second returns success (0).
Build:
gcc -std=c11 -D_POSIX_C_SOURCE=200809L -Wall -Wextra -pthread repro.c -o repro
Run:
./repro
Output:
After owner death: 130 - expected 130 (Owner died)
First retry: 131 - expected 131 (State not recoverable)
Second retry: 0 - expected 131 (State not recoverable)
The reproducer exits with status 1. Source is attached.
An already expired pthread_mutex_timedlock() consistently returned
ENOTRECOVERABLE in a separate local test.
Environment:
dpkg-query -W libc6 libc6-dev gcc
gcc 4:14.2.0-1
libc6:amd64 2.41-12+deb13u4
libc6-dev:amd64 2.41-12+deb13u4
dpkg --print-architecture
amd64
getconf GNU_LIBC_VERSION
glibc 2.41
gcc --version
gcc (Debian 14.2.0-19) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
uname -a
Linux 345f1f893561 6.18.54.1-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Tue
Oct 6 19:13:07 UTC 2026 x86_64 GNU/Linux
cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
NAME="Debian GNU/Linux"
VERSION_ID="13"
VERSION="13 (trixie)"
VERSION_CODENAME=trixie
DEBIAN_VERSION_FULL=13.7
ID=debian
HOME_URL=https://www.debian.org/
SUPPORT_URL=https://www.debian.org/support
BUG_REPORT_URL=https://bugs.debian.org/
Mit freundlichen Grüßen / Kind regards
i. A. Tobias Schülein
Team Leader OS RT System
R&D ASF
KUKA Deutschland GmbH Zugspitzstraße 140, 86165 Augsburg / Germany
www.kuka.com<http://www.kuka.com/>
[email protected]<mailto:[email protected]> T +49 821 797‑3925
KUKA Deutschland GmbH Board of Directors: Michael Jürgens (Chairman), Johan
Naten, Hui Zhang Registered Office: Augsburg HRB 14914
This e-mail may contain confidential and/or privileged information. If you are
not the intended recipient (or have received this e-mail in error) please
notify the sender immediately and destroy this e-mail. Any unauthorized
copying, disclosure or distribution of contents of this e-mail is strictly
forbidden.
Please consider the environment before printing this e-mail.
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static pthread_mutex_t mutex;
static void check(int error)
{
if (error != 0) {
fprintf(stderr, "Unexpected pthread error: %d\n", error);
exit(2);
}
}
static void *owner(void *unused)
{
(void)unused;
check(pthread_mutex_lock(&mutex));
return NULL; /* Exit while holding the mutex. */
}
int main(void)
{
pthread_mutexattr_t attributes;
check(pthread_mutexattr_init(&attributes));
check(pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE));
check(pthread_mutexattr_setrobust(&attributes, PTHREAD_MUTEX_ROBUST));
check(pthread_mutex_init(&mutex, &attributes));
check(pthread_mutexattr_destroy(&attributes));
pthread_t thread;
check(pthread_create(&thread, NULL, owner, NULL));
check(pthread_join(thread, NULL));
int abandoned = pthread_mutex_trylock(&mutex);
printf("After owner death: %d - expected %d (%s)\n", abandoned, EOWNERDEAD,
strerror(EOWNERDEAD));
if (abandoned != EOWNERDEAD)
return 2;
/* Unlock without making consistent, marking the mutex unrecoverable. */
check(pthread_mutex_unlock(&mutex));
int first = pthread_mutex_trylock(&mutex);
int second = pthread_mutex_trylock(&mutex);
printf("First retry: %d - expected %d (%s)\n", first, ENOTRECOVERABLE,
strerror(ENOTRECOVERABLE));
printf("Second retry: %d - expected %d (%s)\n", second, ENOTRECOVERABLE,
strerror(ENOTRECOVERABLE));
return first == ENOTRECOVERABLE && second == ENOTRECOVERABLE ? 0 : 1;
}