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/14076] PTHREAD_MUTEX_LOCK() in multiple threads RETURNING EOWNERDEAD


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

Siddhesh Poyarekar <siddhesh at redhat dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |siddhesh at redhat dot com

--- Comment #4 from Siddhesh Poyarekar <siddhesh at redhat dot com> 2012-10-04 14:45:08 UTC ---
The description is misleading.  Your program does not use threads; it uses
different processes using fork with mutexes in shared memory with pshared set. 
I have modified your program to the following and it shows that the problem is
seen only with forked processes and not with threads:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <wait.h>
#include <sys/mman.h>
#include <assert.h>
#include <pthread.h>

#define zero_or_die(ret, str) \
  ({ \
     if (ret) \
       { \
         printf ("%s: %s\n", str, strerror (ret)); \
     abort (); \
       } \
  })

void
initLock (pthread_mutex_t * mutex)
{
  int ok = 0;
  pthread_mutexattr_t ma;

  ok = pthread_mutexattr_init (&ma);
  zero_or_die (ok, "pthread_mutexattr_init");

  ok = pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK);
  zero_or_die (ok, "pthread_mutexattr_settype");

#ifdef FORK
  ok = pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED);
  zero_or_die (ok, "pthread_mutexattr_setpshared");
#endif

  ok = pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT);
  zero_or_die (ok, "pthread_mutexattr_setprotocol");

  ok = pthread_mutexattr_setrobust (&ma, PTHREAD_MUTEX_ROBUST_NP);
  zero_or_die (ok, "pthread_mutexattr_setrobust");

  ok = pthread_mutex_init (mutex, &ma);
  zero_or_die (ok, "pthread_mutex_init");

  pthread_mutexattr_destroy (&ma);
  printf ("%u: created mutex: %p\n", getpid (), mutex);
}

int
lock (pthread_mutex_t * mutex)
{
  int rc = pthread_mutex_lock (mutex);
  if (rc == EOWNERDEAD)
    {
      int crc = pthread_mutex_consistent (mutex);
      if (crc != 0)
    fprintf (stderr,
         "%u: pthread_mutex_consistent failed: %p %d %s\n",
         getpid (), mutex, crc, strerror (crc));
    }

  else if (rc != 0)
    fprintf (stderr, "%u: pthread_mutex_lock failed: %p %d %s\n",
         getpid (), mutex, rc, strerror (rc));
  return rc;
}

void
unlock (pthread_mutex_t * mutex)
{
  int rc = pthread_mutex_unlock (mutex);
  if (rc != 0)
    fprintf (stderr, "%u: pthread_mutex_unlock failed: %p %d %s\n",
         getpid (), mutex, rc, strerror (rc));
}

void
child (pthread_mutex_t * mutex)
{
  lock (mutex);
  sched_yield ();

#ifdef VERBOSE
  fprintf (stderr, "%d process suicide - abandoning lock %p\n", getpid (),
       mutex);

#endif /*  */

  // abandon the lock (i.e. dont unlock it)
  // unlock(mutex);
}

int
main (int argc, char **argv)
{

#define iterations 500
#define parProcs 10
  int i;
#ifdef FORK
  void *shared = mmap (NULL, sizeof (pthread_mutex_t), PROT_WRITE | PROT_READ,
               MAP_SHARED | MAP_ANON, -1, 0);
  assert (shared != NULL);
  memset (shared, 0, sizeof (pthread_mutex_t));
  pthread_mutex_t *mutex = (pthread_mutex_t *) shared;
#else
  pthread_mutex_t *mutex = malloc (sizeof (pthread_mutex_t));
  pthread_t t[iterations];
#endif

  initLock (mutex);
  lock (mutex);
  unlock (mutex);

  for (i = 0; i < (iterations + parProcs); i++)
    {
      if ((i < iterations))
    {
#ifdef FORK
      if (fork () == 0)
        {
          child (mutex);
          return -1;
        }
#else
      pthread_create (&t[i], NULL, child, mutex);
#endif
    }
    }
  return 0;
}

To build with fork (a variant of your original reproducer):

gcc -DFORK foo.c -pthread

To build it to use pthreads and non-shared memory:

gcc foo.c -pthread

Another thing to note is that the problem is reproducible only when PI is set. 
This is important because in the PI case, it is the kernel that synchronizes
the threads (or in this case, processes) with the FUTEX_LOCK_PI operation.  It
may well end up being a kernel futex bug and not a glibc bug.

-- 
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]