This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug nptl/14652] New: Cancelling a pthread_cond_wait with PRIO_INHERIT mutex causes a deadlock


http://sourceware.org/bugzilla/show_bug.cgi?id=14652

             Bug #: 14652
           Summary: Cancelling a pthread_cond_wait with PRIO_INHERIT mutex
                    causes a deadlock
           Product: glibc
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: nptl
        AssignedTo: unassigned@sourceware.org
        ReportedBy: siddhesh@redhat.com
                CC: drepper.fsp@gmail.com
    Classification: Unclassified


This is different from bug 14477, which is a deadlock due to an incorrect
exception table.  This problem is sometimes seen when a program with multiple
waiters and signallers are cancelled.  One of the waiters could get cancelled
at a point after it has returned successfully from a futex_wait and before it
disables async cancellation.  Since a wait with PRIO_INHERIT mutex uses the
FUTEX_WAIT_REQUEUE_PI futex operation, the futex syscall returns with the mutex
locked.  The cleanup handler subsequently tries to lock this already locked
mutex, resulting in a deadlock.

The following program demonstrates this on i386 as well as x86_64:

#include <pthread.h>
#include <stdio.h>

#define NUM 5
#define ITERS 100000

pthread_mutex_t mutex;
pthread_cond_t cond;

void cleanup (void *u)
{
  pthread_mutex_unlock (&mutex);
}

void *
signaller (void *u)
{
  int i;

  for (i = 0; i < ITERS / NUM; i++)
    {
      pthread_mutex_lock (&mutex);
      pthread_cond_signal (&cond);
      puts ("signalled");
      fflush (stdout);
      pthread_mutex_unlock (&mutex);
    }
}

void *
waiter (void *u)
{
  int i;

  for (i = 0; i < ITERS / NUM; i++)
    {
      struct timespec ts;
      clock_gettime(CLOCK_REALTIME, &ts);
      ts.tv_sec += 20;

      pthread_mutex_lock (&mutex);
      pthread_cleanup_push (cleanup, NULL);
      puts ("waiting...");
      pthread_cond_timedwait (&cond, &mutex, &ts);
      puts ("waited");
      fflush (stdout);
      pthread_mutex_unlock (&mutex);
      pthread_cleanup_pop (0);
    }
}

int
main (void)
{
  pthread_t w[NUM];
  pthread_t s;
  pthread_mutexattr_t attr;
  int i;

  for (i = 0; i < ITERS; i++)
    {
      pthread_mutexattr_init (&attr);
      pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_INHERIT);
      pthread_cond_init (&cond, NULL);
      pthread_mutex_init (&mutex, &attr);

      for (i = 0; i < NUM; i++)
        pthread_create (&w[i], NULL, waiter, NULL);

      pthread_create (&s, NULL, signaller, NULL);

      for (i = 0; i < NUM; i++)
        {
          pthread_cancel (w[i]);
          pthread_join (w[i], NULL);
        }
      pthread_cancel (s);
      pthread_join (s, NULL);
    }

  return 0;
}

The program hangs after some iterations.  I have a patch in the works that
should fix this.

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]