On Sat, Jul 25, 2009 at 03:32, Aurelien Jarno<aurel...@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 ); }