This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Condition variable deadlock with PI mutexes
- From: Tobias RingstrÃm <tobias at ringis dot se>
- To: libc-help at sourceware dot org
- Date: Mon, 05 Mar 2012 17:43:28 +0100
- Subject: Condition variable deadlock with PI mutexes
I think I've found a bug causing a deadlock when using pthread condition
variables with PRIO_INHERIT mutexes, or I'm missing something. I compile
the program at the end of this email with the following options:
gcc -Wall -pthread -D_XOPEN_SOURCE=600 pi_condvar_bug.c
I'm running this on a Fedora 16 (x86_64) machine with gcc 4.6.2 and
kernel 3.2.6-3.fc16.x86_64. I've tested both the Fedora supplied glibc
(2.14.90-24) and a custom built 2.14 with identical results. I've also
built a 32 bit binary using -m32, which again produced identical results.
If I run the program in GDB and break after the deadlock, I get the
following backtrace:
(gdb) thread apply all backtrace
Thread 4 (Thread 0x7ffff6fd4700 (LWP 28864)):
#0 0x0000003b56405970 in __pthread_mutex_lock_full ()
from /lib64/libpthread.so.0
#1 0x00000000004009fd in consumer_thread ()
#2 0x0000003b56407d90 in start_thread () from /lib64/libpthread.so.0
#3 0x0000003b55cef48d in clone () from /lib64/libc.so.6
Thread 3 (Thread 0x7ffff77d5700 (LWP 28863)):
#0 0x0000003b5640bac8 in pthread_cond_wait@@GLIBC_2.3.2 ()
from /lib64/libpthread.so.0
#1 0x0000000000400a15 in consumer_thread ()
#2 0x0000003b56407d90 in start_thread () from /lib64/libpthread.so.0
#3 0x0000003b55cef48d in clone () from /lib64/libc.so.6
Thread 2 (Thread 0x7ffff7fd6700 (LWP 28862)):
#0 0x0000003b56406311 in __pthread_mutex_cond_lock_full ()
from /lib64/libpthread.so.0
#1 0x0000003b5640bb79 in pthread_cond_wait@@GLIBC_2.3.2 ()
from /lib64/libpthread.so.0
#2 0x0000000000400a15 in consumer_thread ()
#3 0x0000003b56407d90 in start_thread () from /lib64/libpthread.so.0
#4 0x0000003b55cef48d in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x7ffff7fd8700 (LWP 28859)):
#0 0x0000003b56405970 in __pthread_mutex_lock_full ()
from /lib64/libpthread.so.0
#1 0x0000000000400b66 in main ()
If I run the binary built statically against vanilla 2.14, I can see more:
Program received signal SIGINT, Interrupt.
__pthread_mutex_lock_full (mutex=0x6be900) at pthread_mutex_lock.c:303
303 if (INTERNAL_SYSCALL_ERROR_P (e, __err)
(gdb) p *mutex
$1 = {__data = {__lock = -2147454520, __count = 1, __owner = 0,
__nusers = 2,
__kind = 34, __spins = 0, __list = {__prev = 0x0, __next = 0x0}},
__size =
"\310q\000\200\001\000\000\000\000\000\000\000\002\000\000\000\"",
'\000' <repeats 22 times>,
__align = 6442480072}
The deadlock only happen if I set the PTHREAD_PRIO_INHERIT attribute on
the mutex.
I'm considering filing a bug in bugzilla, but I wanted to check here first.
/Tobias
----------------------------------------------------------------------
#include <assert.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
pthread_cond_t g_cond;
pthread_mutex_t g_mutex;
int g_num, g_it;
void*
consumer_thread(void *arg)
{
for (;;)
{
if (pthread_mutex_lock(&g_mutex))
abort();
while (g_num <= 0)
{
if (pthread_cond_wait(&g_cond, &g_mutex))
abort();
}
printf("\r%9u", ++g_it);
fflush(stdout);
g_num--;
if (pthread_mutex_unlock(&g_mutex))
abort();
}
}
void
init_mutex(void)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
/* pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); */
/* if (pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) */
/* abort(); */
if (pthread_mutex_init(&g_mutex, &attr))
abort();
}
void
create_thread(void *(*thread_main)(void *))
{
pthread_t t;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
if (pthread_create(&t, &attr, thread_main, NULL))
abort();
}
int
main()
{
int i;
init_mutex();
for (i = 0; i < 3; ++i)
create_thread(consumer_thread);
for (;;)
{
if (pthread_mutex_lock(&g_mutex))
abort();
g_num++;
if (pthread_cond_signal(&g_cond))
abort();
if (pthread_mutex_unlock(&g_mutex))
abort();
}
}