pthread_join leads to segmentation fault. why? - c

This code receives a input file with 10 filenames, stores them into an 2d array and creates 10+1 threads: a requester and 10 converters. This is only a skeleton, so my threads only print their id, thei're not accessing any global or shared variable or something that requires a mutex. So, what should I do to avoid a segmentation fault here?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <math.h>
#include <unistd.h>
#include <errno.h>
#define READ_BUFFER_LEN 16
//#define MAX_LENGTH 128
enum {
MAX_LENGTH = 512
};
typedef struct FileNameArray {
size_t nfiles; /* Number of file names allocated and in use */
size_t maxfiles; /* Number of entries allocated in array */
char **files; /* Array of file names */
} FileNameArray;
//GLOBAL vars
int num_images, *threads_ids /*threads ids*/;
pthread_t *threads;
void deallocate2D(FileNameArray *names) {
size_t i;
for (i = 0; i < names->nfiles; i++)
free(names->files[i]);
free(names->files);
names->nfiles = 0;
names->files = 0;
names->maxfiles = 0;
}
int readInputFile(FILE *fp, FileNameArray *names) {
num_images = names->nfiles;
int max_lines = names->maxfiles;
char **file_names = names->files;
char line[MAX_LENGTH];
char **final_filenames, **array;
while (fgets(line, sizeof line, fp) != NULL) {
if (line[0] != '\n') {
/* Remove newline from end of file name */
char *nl = strchr(line, '\n');
if (nl != 0)
*nl = '\0';
if (num_images >= max_lines) {
max_lines += 100;
array = realloc(file_names, max_lines * sizeof (char*));
if (array == NULL) {
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = max_lines;
names->files = array;
file_names = array;
}
if ((file_names[num_images] = malloc(strlen(line) + 1)) == NULL) {
fprintf(stderr, "Error allocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->nfiles++;
strcpy(file_names[num_images], line);
printf("name of file %d is: %s \n", num_images, file_names[num_images]);
num_images++;
}
}
printf("Num_lines: %d\n", num_images);
//realloc to number of lines in the file, to avoid wasting memory
if ((final_filenames = realloc(file_names, num_images * sizeof (char*))) == NULL) {
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = num_images;
names->files = final_filenames;
return 0;
}
void* requester(void* arg) {
printf("This is the requester thread\n");
//sleep(1);
pthread_exit(NULL);
return NULL;
}
void* converter(void *id) {
int my_id = *((int*) id);
printf("Thread's id is: %d\n", my_id);
pthread_exit(NULL);
return NULL;
}
int main(int argc, char *argv[]) {
FileNameArray names = {0, 0, 0};
int i, rc;
pthread_attr_t attr;
//check parameters
if (argc < 4) {
fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n",
argv[0]);
return -1;
}
printf("Opening input file [%s]\n", argv[1]);
FILE *fpin = fopen(argv[1], "r");
if (fpin == NULL) {
fprintf(stderr, "Could not open input file %s (%s)\n",
argv[1], strerror(errno));
return -1;
}
if ((names.files = malloc(10 * sizeof (char*))) == NULL) {
fprintf(stderr, "Error allocating initial space for 2d array: %s\n",
strerror(errno));
return -1;
}
names.maxfiles = 10;
if (readInputFile(fpin, &names) == -1) {
fprintf(stderr, "Error reading image filenames from input\n");
return -1;
}
threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t));
threads_ids = (int*) malloc(num_images + 1 * sizeof (int));
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//creates requester thread, the 1st one on the list
pthread_create(&threads[0], &attr, requester, &threads_ids[0]);
threads_ids[0] = 0;
//creates so many converter threads as the number of images to convert
for (i = 1; i < num_images + 1; i++) {
threads_ids[i] = i;
rc = pthread_create(&threads[i], &attr, converter, &threads_ids[i]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for (i = 0; i < num_images + 1; i++) {
printf("Waiting for thread nr %d\n", i);
rc = pthread_join(threads[i], NULL);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
fclose(fpin);
free(threads);
free(threads_ids);
printf("###########\n");
deallocate2D(&names);
printf("Done!\n");
return 0;
}
This is one of the possible ouputs:
Num_lines: 10
This is the requester thread
Thread's id is: 1
Thread's id is: 2
Thread's id is: 3
Thread's id is: 5
Thread's id is: 4
Thread's id is: 6
Thread's id is: 7
Thread's id is: 8
Thread's id is: 9
Waiting for thread nr 0
Thread's id is: 10
Segmentation fault
and this is the result of gdb:
Program received signal SIGSEGV, Segmentation fault.
0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
3724 malloc.c: No such file or directory.
in malloc.c
(gdb) where
#0 0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
#1 0x00120802 in *__GI__dl_deallocate_tls (tcb=<value optimized out>,
dealloc_tcb=112) at dl-tls.c:487
#2 0x00133748 in __free_stacks (limit=41943040) at allocatestack.c:274
#3 0x00133849 in queue_stack (pd=0xb5fd9b70) at allocatestack.c:302
#4 __deallocate_stack (pd=0xb5fd9b70) at allocatestack.c:740
#5 0x00134b37 in pthread_join (threadid=3053296496, thread_return=0x0)
at pthread_join.c:110
#6 0x0804955c in main (argc=4, argv=0xbffff4a4) at main.c:261

threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t));
threads_ids = (int*) malloc(num_images + 1 * sizeof (int));
Certainly you must have intended to write
threads = malloc((num_images + 1) * sizeof (pthread_t));
threads_ids = malloc((num_images + 1) * sizeof (int));
or
threads = calloc(num_images + 1, sizeof (pthread_t));
threads_ids = calloc(num_images + 1, sizeof (int));
instead?

Related

C program: Parent read one file and child count the number of words. Child have 4 Threads and mapper and reducer is also used

I am writing a C program in which I have a child and a parent. Parent and child share data using shared memory. What I am doing is asking parent to write the file in shared memory and child process then reads the file from shared memory and outputs a list showing the count of each unique word.
What I have to do is use 4 thread in child program and also use mapper and reducer to accomplish the task.
The text file is having around 30000 lines in it. My program is running correctly if I pass only 20000 lines in the text file but, now running for the whole file.
Please If someone can have a look at my program and let me know where I am going wrong will be surely appreciated.
Here is the link to the text file: http://cis-linux1.temple.edu/~qzeng/cis5512-fall2016/papers/ANNA_KARENINA.txt
And here is the code I am trying to run:
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <ctype.h>
#define NUM_THREADS 4
static key_t key = (key_t) 0;
static int size = 0;
struct thread_data
{
int thread_id;
char *msg;
char* wordary[10000][2];
int size;
};
struct thread_data thread_data_array[NUM_THREADS];
void *CountWords(void *threadarg)
{
int taskid, j, i=0, flag=0, index = 0, p, k,z, cnt, m;
char *msg_words, c, *word, buffer[8];
char* word_array[10000][2];
struct thread_data *my_data;
my_data = (struct thread_data *) threadarg;
taskid = my_data->thread_id;
msg_words = my_data->msg;
strcat(msg_words," ");
word = (char*) malloc(20);
word_array[0][0] = (char*) malloc(30);
word_array[0][1] = (char*) malloc(8);
FILE *out;
if(taskid==0)
out=fopen("out.txt","w");
//printf("%d\n", strlen(msg_words));
for(j=0; j < strlen(msg_words); j++)
{
c = msg_words[j];
c = tolower(c);
if(c == '\n')
{
c = ' ';
}
if(!isspace(c))
{
word[i++] = c;
}
if(c == '\0')
{
break;
}
if(c == ' ')
{
flag = 0;
for(k=0; k <= index; k++)
{
if(0 == strcmp(word_array[k][0],word))
{
flag = 1;
cnt = atoi(word_array[k][1]);
cnt++;
sprintf(buffer, "%d", cnt);
strcpy(word_array[k][1],buffer);
}
}
if(flag == 0)
{
strcpy(word_array[index][0],word);
strcpy(word_array[index][1],"1");
index++;
word_array[index][0]=(char*)malloc(30);
word_array[index][1]=(char*)malloc(8);
}
for(p=0; p <= 20; p++)
{
word[p] = 0;
}
i = 0;
//printf("%d",index);
}
//my_data->size = index;
}
printf("%d\n",index);
my_data->size = index;
for(m = 0; m<index; m++)
{
//printf("%d",m);
my_data->wordary[m][0] = (char*) malloc(30);
my_data->wordary[m][1] = (char*) malloc(8);
strcpy(my_data->wordary[m][0], word_array[m][0]);
strcpy(my_data->wordary[m][1], word_array[m][1]);
//printf("%s %s\n", my_data->wordary[m][0], my_data->wordary[m][1]);
}
pthread_exit((void *)my_data);
}
void main()
{
int ShmID, index = 0;
char* ShmPTR;
pid_t pid;
int status;
clock_t begin, end;
double time_spent;
begin = clock();
FILE *txtfile, *out_file;
txtfile = fopen("test.txt", "r");
fseek(txtfile, 0, SEEK_END); // seek to end of file
size = ftell(txtfile); // get current file pointer
fseek(txtfile, 0, SEEK_SET);
//printf("size : %d", size);
key = ftok(__FILE__,'x');
ShmID = shmget(key, size, IPC_CREAT | 0666);
if (ShmID < 0) {
printf("*** shmget error (server) ***\n");
exit(1);
}
printf("Server has received a shared memory\n");
ShmPTR = (char *) shmat(ShmID, NULL, 0);
if (ShmPTR == (char *)(-1)) {
printf("*** shmat error (server) ***\n");
exit(1);
}
printf("Server has attached the shared memory...\n");
while(!feof(txtfile))
{
ShmPTR[index] = fgetc(txtfile);
index++;
}
//ShmPTR[index] = '\0';
printf("Server is about to fork a child process...\n");
pid = fork();
if (pid < 0)
{
printf("*** fork error (server) ***\n");
exit(1);
}
else if (pid == 0)
{
printf(" Client process started\n");
//printf("%s",shm);
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int rc, t, shmsz1, shmsz2, shmsz3;
char* split_ShmPTR[4];
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//printf("1111");
//printf("%d\n",size);
shmsz1 = (int)(size/4);
shmsz2 = shmsz1*2;
shmsz3 = shmsz1*3;
// printf("%d %d %d\n", shmsz1, shmsz2, shmsz3);
//printf("%c\n",ShmPTR[87]);
while(ShmPTR[shmsz1] != ' ')
{
shmsz1++;
}
//printf("%d \n", shmsz1);
//printf("%c1\n",ShmPTR[shmsz1]);
split_ShmPTR[0] = (char*)malloc(shmsz1 + 1000);
strncpy(split_ShmPTR[0],ShmPTR,shmsz1);
while(ShmPTR[shmsz2] != ' ')
{
shmsz2++;
}
split_ShmPTR[1] = (char*)malloc(shmsz2-shmsz1 + 1000);
strncpy(split_ShmPTR[1],ShmPTR + shmsz1,shmsz2-shmsz1);
while(ShmPTR[shmsz3] != ' ')
{
shmsz3++;
}
split_ShmPTR[2] = (char*)malloc(shmsz3-shmsz2 + 1000);
strncpy(split_ShmPTR[2],ShmPTR + shmsz2,shmsz3-shmsz2);
split_ShmPTR[3] = (char*)malloc(size-shmsz3 + 10);
strncpy(split_ShmPTR[3],ShmPTR + shmsz3,size-shmsz3);
//printf("%s\n",split_ShmPTR[3]);
struct thread_data *my_words;
char* word_array_final[30000][2];
word_array_final[0][0] = (char*)malloc(30);
word_array_final[0][1] = (char*)malloc(8);
int q, r, flag1 = 0, count, idx = 0, z;
char buff[8];
for(t = 0; t<NUM_THREADS; t++)
{
thread_data_array[t].thread_id = t;
thread_data_array[t].msg = split_ShmPTR[t];
rc = pthread_create(&threads[t], NULL, CountWords, (void *) &thread_data_array[t]);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
//pthread_join(threads[t],(void*)&my_words);
//printf("%d %s\n", my_words->thread_id, my_words->wordary[0][0]);
}
//pthread_exit(NULL);
//printf("%s\n", thread_data_array[3].msg);
pthread_attr_destroy(&attr);
for(t = 0; t<NUM_THREADS; t++)
{
pthread_join(threads[t],(void*)&my_words);
//printf("%d %s\n", my_words->thread_id, my_words->wordary[1][0]);
//printf("%d thread\n", t);
//printf("%d",my_words->size);
if(t == 0)
{
//printf("%d %s\n", my_words->thread_id, my_words->wordary[1][0]);
for(q = 0; q < my_words->size; q++)
{
strcpy(word_array_final[idx][0], my_words->wordary[q][0]);
strcpy(word_array_final[idx][1], my_words->wordary[q][1]);
idx++;
word_array_final[idx][0] = (char*)malloc(30);
word_array_final[idx][1] = (char*)malloc(8);
//printf("%s %s\n", word_array_final[idx][0], word_array_final[idx][1]);
}
}
else
{
//printf("%d %s %d\n", my_words->thread_id, my_words->wordary[1][0], my_words->size);
for(q = 0; q<my_words->size; q++)
{
flag1 = 0;
for(r = 0; r<idx; r++)
{
if(0 == (strcmp(word_array_final[r][0],my_words->wordary[q][0])))
{
flag1 = 1;
count = atoi(my_words->wordary[q][1]) + atoi(word_array_final[r][1]);
sprintf(buff, "%d", count);
strcpy(word_array_final[r][1],buff);
}
//printf("%s %s1\n", word_array_final[idx][0], word_array_final[idx][1]);
}
if(flag1 == 0)
{
strcpy(word_array_final[idx][0],my_words->wordary[q][0]);
strcpy(word_array_final[idx][1],my_words->wordary[q][1]);
idx++;
word_array_final[idx][0]=(char*)malloc(30);
word_array_final[idx][1]=(char*)malloc(8);
}
}
}
}
out_file=fopen("output.txt","w");
for(z=0; z<idx; z++)
{
fprintf(out_file, "%s : %s\n", word_array_final[z][1], word_array_final[z][0]);
}
printf("done");
fclose(out_file);
//pthread_exit(NULL);
printf(" Client is about to exit\n");
exit(0);
}
wait(&status);
printf("Server has detected the completion of its child...\n");
shmdt((void *) ShmPTR);
printf("Server has detached its shared memory...\n");
shmctl(ShmID, IPC_RMID, NULL);
printf("Server has removed its shared memory...\n");
printf("Server exits...\n");
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Time spent: %lf\n", time_spent);
exit(0);
}
Please help me guys any help will be surely appreciated.
I found the solution...It a silly mistake...Size of my array was less...Now its fixed...And this program can be used as a child - parent program using shared memory also having mapper and reducers.

pthread_cond_wait in "produce_numbers" gives me segmentation fault

My problem is that I can't initialize the circular_buffer in main() and the basic problem is that when the program calls pthread_cond_wait() in the produce_numbers() function, I take a segmentation fault.
My code is below.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int seed;
typedef struct circular_buffer {
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
pthread_mutex_t mutex; // needed to add/remove data from the buffer
pthread_cond_t can_produce; // signaled when items are removed
pthread_cond_t can_consume; // signaled when items are added
} circular_buffer;
struct thread_data {
int thread_id;
int thread_id2;
int seed;
int numbersofprod;
int talenum;
};
struct thread_data thread_data_array[40];
void cb_init(circular_buffer *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if (cb->buffer == NULL) {
printf("Could not allocate memory..Exiting! \n");
exit(1);
}
// handle error
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
}
// remove first item from circular item void
cb_pop_front(circular_buffer *cb, void *item)
{
printf("pop_front");
if (cb->count == 0) {
printf("Access violation. Buffer is empty\n");
exit(1);
}
memcpy(item, cb->tail, cb->sz);
cb->tail = (char *)cb->tail + cb->sz;
if (cb->tail == cb->buffer_end)
cb->tail = cb->buffer;
cb->count--;
}
// add item to circular buffer
void cb_push_back(circular_buffer *cb, const void *item)
{
if (cb->count == cb->capacity) {
printf("Access violation. Buffer is full\n");
exit(1);
}
memcpy(cb->head, item, cb->sz);
cb->head = (char *)cb->head + cb->sz;
if (cb->head == cb->buffer_end)
cb->head = cb->buffer;
cb->count++;
}
// destroy circular buffer
void cb_free(circular_buffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
}
void *consume_numbers(void *arg)
{
struct thread_data *my_data;
int threadId = my_data->thread_id2;
int rc;
circular_buffer *cb =
(circular_buffer *)arg; // δήλωση δείκτη σε δομή circular_buffer
printf("to capacity einai %d!\n", cb->capacity);
while (1) {
pthread_mutex_lock(&cb->mutex);
// elegxos an to buffer einai adeio
if (cb->count == 0) { // empty
// wait for new items to be appended to the buffer
printf("eeeeeee");
pthread_cond_wait(&cb->can_consume, &cb->mutex);
} // if
int *tmp_read = (int *)malloc(4);
cb_pop_front(cb, (void *)tmp_read);
free(tmp_read);
printf("Thread: consuming item %d!\n", cb->count);
// signal the fact that new items may be produced
rc = pthread_cond_signal(&cb->can_produce);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n", rc);
pthread_exit(&rc);
} // if
rc = pthread_mutex_unlock(&cb->mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
pthread_exit(&rc);
} // if
} // while
// de ftanei pote edw
return NULL;
} // consume_numbers
void *produce_numbers(void *threadarg)
{
struct thread_data *my_data;
my_data = (struct thread_data *)threadarg;
int seeed = my_data->seed;
int numberofprod = my_data->numbersofprod;
int threadId = my_data->thread_id;
int talenumber = my_data->talenum;
int j, r;
int *tid;
int rc;
circular_buffer *cb;
// open file
FILE *f = fopen("producers_in.txt", "w");
if (f == NULL) {
printf("Error opening file!\n");
exit(1);
} // telos anoigmatos arxeiou
srand(seeed); // paragwgi sporou
for (j = 0; j < numberofprod; j++) {
pthread_mutex_lock(&cb->mutex);
// elegxos an o buffer einai full
if (cb->count == cb->capacity) {
// wait until some elements are consumed
printf("mpika");
// pthread_cond_wait(&cb->can_produce, &cb->mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n",
rc);
pthread_exit(&rc);
} // if
} // while
else {
r = rand();
printf("tyxaios arithmos %d\n", r);
cb_push_back(
cb, (void *)&r); // grapse sto arxeio txt ton tyxaio arithmo r
const char *text = "the random number of producer with id";
fprintf(f, "%s ", text);
tid = (int *)threadarg;
fprintf(f, "%d\n", tid);
const char *text2 = "is";
fprintf(f, " %s ", text2);
fprintf(f, "%d\n", r);
printf("to count einai %d\n", cb->count);
// signal the fact that new items may be consumed
rc = pthread_cond_signal(&cb->can_consume);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n",
rc);
pthread_exit(&rc);
} // if
rc = pthread_mutex_unlock(&cb->mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n",
rc);
pthread_exit(&rc);
} // if
} // else
} // for
fclose(f);
// NEVER REACHED
tid = (int *)threadarg;
pthread_exit(tid);
} // produce_numbers
// MAIN
int main(int argc, char *argv[])
{
if (argc != 6) {
printf("ERROR: the program should take 5 argument!\n");
exit(-1);
}
int producers = atoi(argv[1]);
int consumers = atoi(argv[2]);
int numbersofprod = atoi(argv[3]);
int talenum = atoi(argv[4]);
int seed = atoi(argv[5]);
/*elegxoume oti ta dedomena pou dothikan einai swsta.*/
if (producers < 1) {
printf("ERROR: the number of producers to run should be a positive number.Current number given %d.\n",
producers);
exit(-1);
}
if (consumers < 1) {
printf(
"ERROR: the number of consumers to run should be a positive number.Current number given %d.\n", consumers);
exit(-1);
}
if (numbersofprod <
1) {
printf("ERROR: the number of numbersofprod to run should be a positive number. Current number given %d.\n", numbersofprod);
exit(-1);
}
if (talenum < 1) {
printf("ERROR: the number of tale to run should be a positive number. Current number given %d.\n", talenum);
exit(-1);
}
if (seed < 1) {
printf("ERROR: the number of the seed to run should be a positive number. Current number given %d.\n", seed);
exit(-1);
}
printf("Main: We will create %d producer threads", producers);
printf(" and %d consumers threads.\n", consumers);
pthread_t *prod;
pthread_t *cons;
prod = malloc(producers * sizeof(pthread_t));
if (prod == NULL) {
printf("NOT ENOUGH MEMORY!\n");
return -1;
}
cons = malloc(consumers * sizeof(pthread_t));
if (cons == NULL) {
printf("NOT ENOUGH MEMORY!\n");
return -1;
}
int rc;
int rc2;
int threadCount;
int threadCount2;
int countArray[producers];
int countArray2[consumers];
//INITIALIZE MUTEX AND CONDITION VARIABLES
circular_buffer cb = {
.count=0,
.mutex = PTHREAD_MUTEX_INITIALIZER,
.can_produce = PTHREAD_COND_INITIALIZER,
.can_consume = PTHREAD_COND_INITIALIZER
};
cb_init(cb, talenum, 1); //end_of initializing
for (threadCount = 0; threadCount < producers; threadCount++) {
printf("Main: creating thread %d for producers\n ",
threadCount);
countArray[threadCount] = threadCount + 1;
thread_data_array[threadCount].thread_id = threadCount;
thread_data_array[threadCount].talenum = talenum;
thread_data_array[threadCount].seed = seed;
thread_data_array[threadCount].numbersofprod =
numbersofprod; /*dimiourgia tou thread*/
rc = pthread_create(&prod[threadCount], NULL, produce_numbers,
(void *)&thread_data_array[threadCount]);
/*elegxos oti to thread dimiourgithike swsta.*/
if (rc != 0) {
printf("ERROR: return code from pthread_create() is %d\n",
rc);
exit(-1);
}
for (threadCount2 = 0; threadCount2 < consumers;
threadCount2++) {
countArray2[threadCount2] = threadCount2 + 1;
thread_data_array[threadCount2].thread_id2 = threadCount2;
printf("Main: creating thread %d for consumers\n",
threadCount);
/*dimiourgia tou thread*/
rc2 = pthread_create(cons, NULL, consume_numbers,
(void *)&cb);
/*elegxos oti to thread dimiourgithike swsta.*/
if (rc2 != 0) {
printf(
"ERROR: return code from pthread_create() is %d\n",
rc2);
exit(-1);
}
}
}
void *status;
for (threadCount = 0; threadCount < producers;
threadCount++) {
rc = pthread_join(prod[threadCount], &status);
if (rc != 0) {
printf("ERROR: return code from pthread_join() is %d\n",
rc);
exit(-1);
}
printf("Main: Thread %d returned %d as status code.\n",
countArray[threadCount], (*(int *)status));
}
free(prod);
`` return 1;
void *status2;
for (threadCount2 = 0; threadCount2 < consumers; threadCount2++) {
rc2 = pthread_join(cons[threadCount2], &status2);
if (rc2 != 0) {
printf("ERROR: return code from pthread_join() is %d\n",
rc);
exit(-1);
}
printf("Main: Thread % d returned % d as status code.\n ", countArray2[threadCount2],
(*(int *)status2));
}
free(cons);
return 1;
}
Your problem is that you never call pthread_cond_init() on the cb.can_produce and cb.can_consume condition variables that are members of the struct circular_buffer.
You need to change the cb_init() function so that it initialises the new circular_buffer's mutex, can_produce and can_consume members with pthread_mutex_init() and pthread_cond_init().
You are also using the pointer variable cb uninitialised in the produce_numbers() function - it's declared as struct circular_buffer *cb; but never assigned to. You need to make cb a member of struct thread_arg instead, and set it in main() so that produce_numbers() has a reference to the same struct circular_buffer object as the other threads.

Segmentation fault multithreading with file open

I created a program to get all files in a directory, find the individual checksums and then find the total checksums using multithreading.
I am receiving a segmentation fault so I ran gdb and saw that the error is on line 60 where open() is. After researching the seg fault on SO, and on other forums, I attempted to implement a few different approaches such as changing open() to fopen() with a FILE *handle rather than an int. That change proved incorrect.
After hours of debugging and searching, I am clueless and would greatly appreciate any insight.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h> ///Compile with -pthread or -lpthread
#include <sys/stat.h>
#define BUFFER_SIZE (1<<16)
void cleanup();
void get_filenames();
void* get_checksum();
char **filenames;
int file_cnt;
DIR *dir;
//int handle;
FILE *handle;
unsigned int checksum;
unsigned char* ptr;
int length;
int count;
unsigned char* buffer;
int* sum;
unsigned int total = 0;
int main(int argc, char *argv[]){
int i;
pthread_t* file;
atexit(cleanup);
get_filenames();
printf("There are %d files:\n", file_cnt);
file = calloc(sizeof(pthread_t), file_cnt);
sum = calloc(sizeof(int), file_cnt);
for(i=0; i<file_cnt; i++){
printf("%s\n", filenames[i]);
pthread_create(&(file[i]), NULL, get_checksum, (void*)&filenames[i]);
}
for(i=0; i<file_cnt; i++){
total += sum[i];
}
printf("total is: %u\n", total);
return EXIT_SUCCESS;
}
void* get_checksum(void* a){
int b = *((int *)a);
//handle = open(filenames[b], O_RDONLY); //SEG FAULT HERE
handle = fopen(filenames[b], "r"); //SEG FAULT HERE
if( handle == NULL ){
printf( "Can't open file: %s\n", filenames[b]);
exit(1);
}
buffer = malloc(BUFFER_SIZE);
if( buffer == NULL ){
printf( "Can't get enough memory\n" );
exit(1);
}
checksum = 0;
do{
//length = read( handle, buffer, BUFFER_SIZE );
length = read( handle, buffer, (sizeof(char)));
if( length == -1 ){
printf( "Error reading file: %s\n", filenames[b]);
//return NULL;
exit(1);
}
ptr = buffer;
count = length;
while( count-- ){
checksum = checksum + (unsigned int)( *ptr++ );
sum[b] = checksum;
}
} while( length );
printf("Checksum= %d\nTimes at: %d\n", checksum, (int)clock());
}
void cleanup() {
if(filenames && file_cnt > 0) {
while(file_cnt-- > 0) {
if(filenames[file_cnt]) {
free(filenames[file_cnt]);
}
}
free(filenames);
}
if(dir) {
closedir(dir);
}
return;
}
void get_filenames() {
struct dirent *dir_entry;
if((dir = opendir(".")) == NULL) {
fprintf(stderr, "Couldn't open the directory entry for reading\n");
exit(1);
}
errno = 0;
file_cnt = 0;
while((dir_entry = readdir(dir)) != NULL) {
char **new_filenames = filenames;
static int realative_dirs = 0;
if(realative_dirs < 2 &&
(strcmp(".", dir_entry->d_name) == 0 || strcmp("..", dir_entry->d_name) == 0)
) {
realative_dirs++;
continue;
}
new_filenames = (char **)realloc(filenames, sizeof(char **) * (file_cnt + 1));
if(new_filenames == NULL) {
free(filenames[file_cnt]);
fprintf(stderr, "Could not allocate reference for filename[%d]\n", file_cnt);
exit(1);
}
filenames = new_filenames;
filenames[file_cnt] = (char *)calloc(strlen(dir_entry->d_name) + 1, sizeof(char));
if(filenames[file_cnt] == NULL) {
fprintf(stderr, "Could not allocate memory for filename[%d]'s string: \"%s\"\n",
file_cnt, dir_entry->d_name);
exit(1);
}
strcpy(filenames[file_cnt], dir_entry->d_name);
file_cnt++;
}
if(errno != 0) {
fprintf(stderr, "An error occured getting the filenam list\n");
exit(1);
}
return;
}
Below is the output and gdb debugging:
There are 24 files:
.windows
.xscreensaver
.alias
.cshrc
Segmentation fault
(gdb) run
Starting program: /home/nolooking/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
There are 24 files:
.windows
[New Thread 0x7ffff781e700 (LWP 15957)]
.xscreensaver
[New Thread 0x7ffff701d700 (LWP 15958)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff781e700 (LWP 15957)]
0x0000000000400d53 in get_checksum (a=0x60b610) at checksum.c:60
60 handle = open(filenames[b], O_RDONLY);
(gdb) backtrace
#0 0x0000000000400d53 in get_checksum (a=0x60b610) at checksum.c:60
#1 0x00007ffff7bc6374 in start_thread () from /lib64/libpthread.so.0
#2 0x00007ffff7907c3d in clone () from /lib64/libc.so.6
(gdb) quit
A debugging session is active.
UPDATE:
I took the advice of one user in the comments who suggested that I use:
handle=fopen((char*)a, "r");. I can successfully print out the file names when the if statement if(handle==NULL) is commented out. When I include that if statement I receive the following output:
There are 24 files:
.windows
.xscreensaver
.alias
.cshrc
Can't open file: p▒`
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/stat.h>
#define BUFFER_SIZE (1<<16)
void cleanup();
void get_filenames();
void* get_checksum();
char **filenames;
int file_cnt;
DIR *dir;
//int handle;
FILE *handle;
unsigned int checksum;
unsigned char* ptr;
int length;
int count;
unsigned char* buffer;
int* sum;
unsigned int total = 0;
int main(int argc, char *argv[]){
int i;
pthread_t* file;
atexit(cleanup);
get_filenames();
printf("There are %d files:\n", file_cnt);
file = calloc(sizeof(pthread_t), file_cnt);
sum = calloc(sizeof(int), file_cnt);
for(i=0; i<file_cnt; i++){
printf("%s\n", filenames[i]);
pthread_create(&(file[i]), NULL, get_checksum, (void*)&filenames[i]);
}
for(i=0; i<file_cnt; i++){
total += sum[i];
}
printf("total is: %u\n", total);
return EXIT_SUCCESS;
}
void* get_checksum(void* a){
int b = *((int *)a);
handle = fopen(((char*)a), "r");
if( handle == NULL ){
printf( "Can't open file: %s\n", ((char*)a));
exit(1);
}
buffer = malloc(BUFFER_SIZE);
if( buffer == NULL ){
printf( "Can't get enough memory\n" );
exit(1);
}
checksum = 0;
do{
length = read( handle, buffer, BUFFER_SIZE );
if( length == -1 ){
printf( "Error reading file: %s\n", ((char*)a));
//return NULL;
exit(1);
}
ptr = buffer;
count = length;
while( count-- ){
checksum = checksum + (unsigned int)( *ptr++ );
//sum[a] = checksum;
}
} while( length );
printf("Checksum= %d\nTimes at: %d\n", checksum, (int)clock());
}
void cleanup() {
if(filenames && file_cnt > 0) {
while(file_cnt-- > 0) {
if(filenames[file_cnt]) {
free(filenames[file_cnt]);
}
}
free(filenames);
}
if(dir) {
closedir(dir);
}
return;
}
void get_filenames() {
struct dirent *dir_entry;
if((dir = opendir(".")) == NULL) {
fprintf(stderr, "Couldn't open the directory entry for reading\n");
exit(1);
}
errno = 0;
file_cnt = 0;
while((dir_entry = readdir(dir)) != NULL) {
char **new_filenames = filenames;
static int realative_dirs = 0;
if(realative_dirs < 2 &&
(strcmp(".", dir_entry->d_name) == 0 || strcmp("..", dir_entry->d_name) == 0)
) {
realative_dirs++;
continue;
}
new_filenames = (char **)realloc(filenames, sizeof(char **) * (file_cnt + 1));
if(new_filenames == NULL) {
free(filenames[file_cnt]);
fprintf(stderr, "Could not allocate reference for filename[%d]\n", file_cnt);
exit(1);
}
filenames = new_filenames;
filenames[file_cnt] = (char *)calloc(strlen(dir_entry->d_name) + 1, sizeof(char));
if(filenames[file_cnt] == NULL) {
fprintf(stderr, "Could not allocate memory for filename[%d]'s string: \"%s\"\n",
file_cnt, dir_entry->d_name);
exit(1);
}
strcpy(filenames[file_cnt], dir_entry->d_name);
file_cnt++;
}
if(errno != 0) {
fprintf(stderr, "An error occured getting the filenam list\n");
exit(1);
}
return;
}
Why I am receiving that output once I uncomment the if statement?
Change this
pthread_create(&(file[i]), NULL, get_checksum, (void*)&filenames[i]);
to be
pthread_create(&(file[i]), NULL, get_checksum, (void*)i);
and this
int b = *((int *)a);
to be
int b = (int)a;
Also you cannot call read() on a FILE* as it is returned by fopen(). Use fread() instead.
Don't use &i. I'll explain in a bit. The argument you're passing to the thread is wrong a is not an integer. It's meant to be a pointer to a string...
Change the thread create to this...
pthread_create(&(file[i]), NULL, get_checksum, filenames[i]);
then print the string as follows...
void* get_checksum(void *a){
char *file_name = (char *)a;
printf("filename=%s\n", file_name);
You're passing the string as a pointer to the called function. In your code you're trying to use this as an index into the array.
If you want to pass the index as an integer beware... this won't work..
pthread_create(&(file[i]), NULL, get_checksum, &i);
This is multithreaded and the value pointed to by &i is changing as the loop runs. Pass the pointer to the string and do not under any circumstances change filenames as the threads run.
I think your problem is simply because you are passing &filenames[i] instead of simply &i.
Then in void* get_checksum(void* a) you are trying to use a char* as an int.
The code would be more like :
for(i=0; i<file_cnt; i++){
printf("%s\n", filenames[i]);
pthread_create(&(file[i]), NULL, get_checksum, (void*)&i);
}
and in void* get_checksum(void* a) :
int b = *((int *)a);
handle = fopen(filenames[b], "r");
if( handle == NULL ){
printf( "Can't open file: %s\n", filenames[b]);
exit(1);
}

print garbage values from the shared memory

I am currently working on a producer-consumer implementation using C.
First, I create a buffer on the shared memory of a variable length that is given by the user in the consumer process.
Then, in the producer process, I need to access the shared memory and puts new data to the buffer so the consumer can consume.
Below is the consumer code:
#include "common.h"
#include <unistd.h>
int fd;
int errno;
int MY_LEN = 0;
Shared* shared_mem;
char *job[4];
int setup_shared_memory(){
fd = shm_open(MY_SHM, O_CREAT | O_RDWR, 0666);
if(fd == -1){
printf("shm_open() failed\n");
exit(1);
}
ftruncate(fd, sizeof(Shared) + MY_LEN*sizeof(char *));
}
int attach_shared_memory(){
shared_mem = (Shared*) mmap(NULL, sizeof(Shared) + MY_LEN*sizeof(char *), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(shared_mem == MAP_FAILED){
printf("mmap() failed\n");
exit(1);
}
return 0;
}
int init_shared_memory() {
shared_mem->data = 0;
int i;
for(i = 0; i < shared_mem->length; i++)
{
shared_mem->arr[i] = 0;
// shared_mem->arr[i] = (char *)calloc(1, sizeof(char*));
}
sem_init(&(shared_mem->mutex), 1, 1);
}
int init_job(){
int i;
for(i = 0; i < 4; i++)
{
job[i] = (char *)malloc(sizeof(char *));
}
}
int take_a_job(int index){
init_job();
char *ds = strdup(shared_mem->arr[index]);
job[0] = strtok(ds, "-");
int i = 1;
while(i < 4)
{
job[i] = strtok(NULL, "-");
i++;
}
// remove the job from the buffer
shared_mem->arr[index] = NULL;
}
int consume_job(int index){
printf("\nPrinter starts printing the job %s, %s pages from Buffer[%d]. The duration is %s seconds and the source is %s.\n",job[3], job[2], index, job[1], job[0]);
sleep(atoi(job[1])); // sleep for job[1] seconds.
}
int main(int args, char *argv[]) {
setup_shared_memory();
attach_shared_memory();
init_shared_memory();
MY_LEN = atoi(argv[1]); // the first parameter following ./printer = the length of the buffer
shared_mem->length = MY_LEN;
//shared_mem->arr = (int*) &shared_mem->arr;
int index = 1;
*(shared_mem->arr) = "1-10-5-6";
*(shared_mem->arr + 1) = "2-5-2-7";
*(shared_mem->arr + 2) = "3-20-10-8";
*(shared_mem->arr + 3) = "4-7-4-9";
take_a_job(index);
int i;
for(i = 0; i < shared_mem->length; i++){
printf("\n\n%d set %s\n", i, shared_mem->arr[i]);
}
consume_job(index);
printf("\n\nHello second check\n\n");
while (1) {}
return 0;
}
Here is the producer code:
#include "common.h"
int fd;
Shared* shared_mem;
char *job;
int setup_shared_memory(){
fd = shm_open(MY_SHM, O_RDWR, 0666);
if(fd == -1){
printf("shm_open() failed\n");
exit(1);
}
}
int attach_shared_memory(){
shared_mem = (Shared*) mmap(NULL, sizeof(Shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(shared_mem == MAP_FAILED){
printf("mmap() failed\n");
exit(1);
}
return 0;
}
int create_a_job(int args, char *argv[]){
int i;
job = (char *)calloc(8, sizeof(char *));
if(args != 5)
return 0; //the parameters are not correctly formatted
else{
for(i = 1; i < args; i++)
{
if(i > 1)
strcat(job, "-");
strcat(job, argv[i]);
}
}
strcat(job, "\0");
printf("\nthe job is %s\n", job);
}
int put_a_job(){
printf("shared_mem->length is %d\n\n", shared_mem->length);
int i;
for(i = 0; i < shared_mem->length; i++)
{
if(*(shared_mem->arr + i) == 0)
{
//shared_mem->arr[i] = (char *)malloc(sizeof(job));
//strcpy(shared_mem->arr[i], job);
*(shared_mem->arr + i) = (char *)job;
printf("\n\nThe index is %d\n", i);
//printf("\n\nthe argument is %s at %d\n", job, i);
return i;
}
}
printf("\n\nThe index is %d\n", i);
}
int main(int args, char *argv[]) {
setup_shared_memory();
attach_shared_memory();
// create a job with the parameters
int result = create_a_job(args, argv);
if(result == 0)
{
printf("Not the right parameters.\n");
printf("Plase enter client ID, job duration, number of pages and job ID.\n");
return 0;
}
int i;
put_a_job();
for (i=0; i < shared_mem->length; i++) {
printf("the argument is %s at %d\n", (char *)(shared_mem->arr + i), i);
}
printf("\n\n");
return 0;
}
The common.h file is
#ifndef _INCLUDE_COMMON_H_
#define _INCLUDE_COMMON_H_
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
// from `man shm_open`
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <string.h>
#include <semaphore.h>
#define MY_SHM "/JIT"
typedef struct {
sem_t mutex;
int data;
int length; // the length of the buffer
char *arr[0];
} Shared;
#endif //_INCLUDE_COMMON_H_
I first run ./consumer 10 & to allocate a buffer of length 10 and after, I run ./producer 1 2 3 4 to put the job to the buffer and print the buffer, I got garbage values
Any help would be really appreciated! Thank you!
Instruction
*(shared_mem->arr + i) = (char *)job;
is storing the pointer job into the shared mem, not the pointed value.
Maybe you want to use a strncpy.
You cannot share memory address between processes, because of Linux uses virtual memory. To make the story short an address in a process is not valid for a different process.
Be aware that you have a memory leakage because you never call free() for the allocated job.

segmentation fault occur on thread program

I am new in thread program. I wrote a C program for executing threads which reverse the command line string and print the both original and reversed string. My program is here:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<pthread.h>
#include<string.h>
typedef struct
{
char *input_string;
char *rev_string;
}data;
void* rev_string(void* arg)
{
int len = 0,index1 = 0,
index2 = 0;
data* names = NULL; /*bject creation*/
names = (data*)malloc(sizeof(data));
if( NULL == names)
{
printf("malloc failure\n");
exit(1);
}
printf("thread recvd = %s\n",(char*)arg);
len = strlen((char*)arg);
names->input_string = (char*)malloc(sizeof(char)*(len+1));
if( NULL == names->input_string)
{
printf("malloc failure\n");
exit(1);
}
strncpy(names->input_string,(char*)arg,len); /*copying input_string to the struct*/
names->rev_string = (char*)malloc(sizeof(char)*(len+1));
if( NULL == names->rev_string)
{
printf("malloc failure\n");
exit(1);
}
for(index1 = len-1 ; index1 >= 0 ; index1--)
{
names->rev_string[index2] = names->input_string[index1];
index2++;
}
pthread_exit((void*)names);
}
Main program:
int main(int argc,char* argv[])
{
int no_of_strings = 0,
len = 0,
status = 0,
ret = 0 ,
index = 0;
pthread_t id[index]; /*thread identifier*/
void* retval = NULL; /*retval to store the value returned by thread job */
data *strings = NULL;/*object creation*/
if(1 >= argc)
{
printf(" please do enter the commands as of below shown format\n");
printf("<exe.c> <string1> <string2> ...<string(N)>\n");
exit(1);
}
no_of_strings = argc - 1 ; /* no of strings entered */
/*creation of threads*/
for(index = 0; index < no_of_strings ;index++)
{
status = pthread_create(&id[index],NULL,rev_string,(void*)argv[index + 1]);
if(status != 0)
{
printf("ERROR in creating thread\n");
exit(1);
}
else
{
printf("thread %d created\n",index+1); }
}
for(index = 0 ;index < no_of_strings;index++)
{
ret = pthread_join(id[index],&retval);
if(ret)
{
printf("Error in joining %d\n", ret);
exit(1);
}
printf("the input_string = %s and its reverse = %s\n",((data*)retval)->input_string,((data*)retval)->rev_string);
}
// free(retval->input_string);
// free(retval->rev_string);
// free(retval);
pthread_exit(NULL);
exit(0);
}
It works on 2 string from command line argument. But got segmentation fault when more than strings. Why? Any errors? Help me.
pthread_t id[index];
id has zero length because index == 0. So any assignment to its elements is undefined behavior. Initialize the array with some positive length, e.g:
const int MAX_THREADS = 10;
pthread_t id[MAX_THREADS]; /*thread identifier*/

Resources