I am getting acquainted with pthreads programming; the following code is a simple producer/consumer design where data is put/fetched from a global list. The problem is: the data pointer in the consumer function is tried to be freed twice. Beside, if I add a printf()
at the beginning of the loop, everything seems ok... What am I doing wrong? I suspect a misuse of the volatile
keyword, or something hidden by the cache... Unless it's just a design issue (which probably is :p).
Thanks for your insights.
Note: malloc()/free()
is thread-safe on my system. I am compiling with $ gcc -pthread -O0
which should, I guess, reduce possible design errors due to misuse of volatile
. Finally, we don't care in this code snippet with running out of memory (in case of more producer than consumer).
Edit: Changed code to a single list head.
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t lock;
pthread_cond_t new_data;
struct data {
int i;
struct data *next;
};
struct data *list_head = NULL;
void *consume(void *arg)
{
struct data *data;
while (1) {
pthread_mutex_lock(&lock);
while (list_head == NULL) {
pthread_cond_wait(&new_data, &lock);
}
data = list_head;
list_head = list_head->next;
pthread_mutex_unlock(&lock);
free(data);
}
return NULL;
}
void *produce(void *arg)
{
struct data *data;
while (1) {
data = malloc(sizeof(struct data));
pthread_mutex_lock(&lock);
data->next = list_head;
list_head = data;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&new_data);
}
return NULL;
}
int main()
{
pthread_t tid[2];
int i;
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&new_data, NULL);
pthread_create(&tid[0], NULL, consume, NULL);
pthread_create(&tid[1], NULL, produce, NULL);
for (i = 0; i < 2; i++) {
pthread_join(tid[i], NULL);
}
}
And the output:
$ ./a.out
*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x00007f5870109000 ***