I'm working on creating a simple threaded producer/consumer example using separate classes, c++ standard library deques, and boost threads on Linux. I'm passing a shared buffer, lock, and condition variables by reference as member variables to my classes. The threads start up ok, but typically crash at a random time due to a lock assertion error.
main: ../nptl/pthread_mutex_lock.c:80: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
Here's how I'm starting the threads in main
std::deque<double> buf;
boost::condition_variable_any buf_has_space;
boost::condition_variable_any buf_has_data;
boost::mutex buf_lock;
boost::thread producerThread(load_func, &buf, &buf_has_space, &buf_has_data, &buf_lock);
boost::thread consumerThread(consume_func, &buf, &buf_has_space, &buf_has_data, &buf_lock);
producerThread.join();
consumerThread.join();
producerThread and consumerThread initialize and run instances of myProducer and myConsumer.
Relevant code from myProducer:
void myProducer::add_to_buffer(){
//Main loop
for (int i=0; i<100000; i++){
boost::mutex::scoped_lock lock(*buffer_lock);
while (buffer->size() == max_size){
buffer_has_space->wait(*buffer_lock);
}
buffer->push_back(i);
buffer_has_data->notify_one();
buffer_lock -> unlock();
}
//Consumer will stop when it sees -1
boost::mutex::scoped_lock lock(*buffer_lock);
while (buffer->size() == max_size){
buffer_has_space->wait(*buffer_lock);
}
buffer->push_back(-1.0);
buffer_has_data->notify_one();
buffer_lock -> unlock();
}
Relevant code from myConsumer:
void myConsumer::load_from_buffer(){
double current = 0;
while (current != -1.0) {
boost::mutex::scoped_lock lock(*buffer_lock);
while (buffer->size() == 0){
buffer_has_data->wait(*buffer_lock);
}
current = buffer->front();
buffer->pop_front();
buffer_has_space->notify_one();
buffer_lock->unlock();
std::cout << current <<"\n";
}
}
I've looked at these questions:
pthread_mutex_lock.c:62: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed
However, the program is crashing before my classes are deconstructed, and each lock is matched with an unlock in the same thread.
buffer_lock -> unlock();- perhaps thescoped_lockis a little peeved when it tries to do exactly what its name implies (lock for scope) since you already unlocked the mutex manually. I.e. it tries to unlock that which it thinks it owns, and can't. The scoped lock should be the object of the waiter's desire; not the bare mutex. - WhozCraig