Condition variable deadlock with PI mutexes

Tobias Ringström tobias@ringis.se
Mon Mar 5 16:43:00 GMT 2012


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();
     }
}



More information about the Libc-help mailing list