[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#479952: libc6: Also in x86_64?



On Sat, Jul 25, 2009 at 03:32, Aurelien Jarno<aurelien@aurel32.net> wrote:
> On Sat, Jul 25, 2009 at 02:11:51AM -0400, Will Murnane wrote:
>> Package: libc6
>> Version: 2.9-21
>> Severity: normal
>>
>> I wrote a program that uses pthreads to accomplish work, and hit this bug in it.  It works properly on Rhel5, so I'm pretty sure it's libc at fault.
>>
>> Full source code available on request.  Basically, though, the problem comes when many threads are fighting for a mutex, and doing very little work between trying to obtain the lock.
>>
>
> If you have a small code to reproduce the problem, it will be highly
> appreciated.
Attached is break_pthreads.cpp.  Compile with
g++ -g -Wall -Werror -pipe -O3 -Wno-deprecated break_pthreads.cpp -o
break_pthreads.o -c
g++ -g -pthread break_pthreads.o -o break_pthreads

Now run it and it crashes:
break_pthreads: pthread_mutex_lock.c:87: __pthread_mutex_lock:
Assertion `mutex->__data.__owner == 0' failed.
Aborted

Will
#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <vector>
#include <signal.h>

struct thread_data {
    int tid;
};

struct work {
  int i;
};

void clean_exit_on_sig(int sig_num)
{
  std::cout << "Got signal " << sig_num << std::endl;
  exit(1);
}

unsigned int NUM_THREADS;
#define WORKTOGET 5

std::vector<work> toDo;
pthread_mutex_t work_lock = PTHREAD_MUTEX_INITIALIZER;

void finishWork(work w)
{
}

void *worker(void *threadarg)
{
  work workingOn[WORKTOGET];
  while (true)
  {
    unsigned int workgot = 0;
    pthread_mutex_lock(&work_lock);
    if (toDo.empty())
    {
      pthread_mutex_unlock(&work_lock);
      pthread_yield();
    } else {
      while (!toDo.empty() && (workgot < WORKTOGET))
      {
        workingOn[workgot] = toDo.back();
        toDo.pop_back();
        workgot++;
      }
    }
    pthread_mutex_unlock(&work_lock);
    for (unsigned int i = 0; i < workgot; i++)
    {
      finishWork(workingOn[i]);
    }
  }
  return NULL;
}

int main( int argc, char **argv )
{
  bool done=false;
  /* Set up SIGSEGV handler */
  signal(SIGSEGV, clean_exit_on_sig);
  /* Set up pthreads stuff */
  NUM_THREADS = sysconf(_SC_NPROCESSORS_CONF);
  pthread_t *workers = (pthread_t*)malloc(NUM_THREADS * sizeof(pthread_t));
  struct thread_data *children = (struct thread_data*)malloc(NUM_THREADS * sizeof(struct thread_data));
  int rc;
  pthread_attr_t attr;
  /* Initialize and set thread detached attribute */
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  
  for (unsigned int t = 0; t < NUM_THREADS; t++)
  {
    children[t].tid = t;
    rc = pthread_create(&workers[t], &attr, &worker, (void *)&children[t]);
    if (rc)
    {
      std::cerr << "ERROR: return code from pthread_create() is " << rc << std::endl;
      exit(-1);
    }
  }
  /* wait for events */
  while ( !done )
  {
  }

  return( 0 );
}

Reply to: