Bug#551903: libc6-i686 pthread_cond_wait fails to reacquire mutex upon cancellation
On Sat, Jun 05, 2010 at 06:39:24PM +0200, Aurelien Jarno wrote:
> On Fri, Jun 04, 2010 at 11:25:28AM +0200, Aurelien Jarno wrote:
> > Aurelien Jarno a écrit :
> > > On Thu, Jun 03, 2010 at 10:09:45PM +0300, Rémi Denis-Courmont wrote:
> > >> Le jeudi 3 juin 2010 22:00:13 Aurelien Jarno, vous avez écrit :
> > >>> I have found a machine with almost the same CPU, the only difference
> > >>> being the speed (3.00 GHz instead of 2.80 GHz). I am unable to reproduce
> > >>> the problem, I have run the testcase more than 200000 times over last
> > >>> night.
> > >> With SMT ("HyperThread") support?
> > >
> > > Yes, with HyperThreading enabled.
> > >
> > >>> Maybe the problem is actually not in the GNU libc. What kernel are you
> > >>> running?
> > >> Normally, I use upstream 2.6.32.15 at the moment.
> > >> But I also hit the bug with Debian 2.6.32-5-686.
> > >>
> > >
> > > I tried on a 2.6.26 kernel, I'll try to reproduce it with this kernel.
> > >
> >
> > I tried on a 2.6.32-5-686 kernel, and it hasn't failed in more than
> > 300000 loops. There is probably something different on your system
> > causing the issue.
> >
>
> I have modified a bit the testcase so that it runs in a loop, and I
> removed all timing functions (see attached file). I am able to reproduce
> the problem in some conditions:
This time it is.
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
/* gcc -O2 -Wall -lpthread condfail.c */
#define _GNU_SOURCE 1
#undef NDEBUG
#include <pthread.h>
#include <time.h>
#include <assert.h>
#include <stdio.h>
static pthread_cond_t wait = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t lock = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
static long long int i=0;
static void cleanup_lock(void *lock)
{
int val;
i++;
val = pthread_mutex_unlock(lock);
if (val != 0) {
printf("failed after %lli iterations\n", i);
assert (0);
}
}
static void *entry(void *barrier)
{
pthread_mutex_lock(&lock);
pthread_cleanup_push(cleanup_lock, &lock);
pthread_barrier_wait(barrier);
for (;;)
pthread_cond_wait(&wait, &lock);
pthread_cleanup_pop(0);
assert(0);
}
int main (void)
{
for(;;) {
pthread_t th;
pthread_barrier_t barrier;
pthread_barrier_init(&barrier, NULL, 2);
pthread_create(&th, NULL, entry, &barrier);
pthread_barrier_wait(&barrier);
pthread_barrier_destroy(&barrier);
pthread_cancel(th);
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
pthread_join(th, NULL);
}
return 0;
}
Reply to: