This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug nptl/14076] PTHREAD_MUTEX_LOCK() in multiple threads RETURNING EOWNERDEAD
- From: "siddhesh at redhat dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: Thu, 04 Oct 2012 14:45:08 +0000
- Subject: [Bug nptl/14076] PTHREAD_MUTEX_LOCK() in multiple threads RETURNING EOWNERDEAD
- Auto-submitted: auto-generated
- References: <bug-14076-131@http.sourceware.org/bugzilla/>
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.