Wrong argument parsing with multithreading - c - c

Im working on a project that is mainly producer-consumer with pthread conditions and mutexes on a circular buffer. The user gives how many consumers and producer threads it wants, random number generator seed, how many numbers each producer produces and the size of the circular buffer. All of them along with the condition and the mutex are global variables
Here is the producer thread code
void * newProducer(void * t){
// Get the thread id
int * a = (int *) t;
int id = *a;
printf("Producer thread %d started!\n", id);
int i;
//Get the seed
//seed is global vairable(Random number generator seed
unsigned int thread_seed = seed * id;
//Allocate memory for the array to save the numbers
int * numbers = (int *) malloc(sizeof(int) * n);
//Open the files
FILE * producer_file = fopen("prods_out.txt", "w");
if(producer_file == NULL){
printf("ERROR: fopen failed.\n");
exit(1);
}
fprintf(producer_file, "-- PRODUCER DATA --\n");
//Produce the numbers
for( i = 0; i < n; i++){
numbers[i] = rand_r(&thread_seed) % 100;
//Lock mutex
if(pthread_mutex_lock(&mutex) < 0){
printf("ERROR: pthread_mutex_lock failed.\n");
exit(1);
}
//printf("Producer thread <%d> locked mutex\n", *id);
//Wait until the cb has space to store numbers
while(cb->count == cb->capacity) {
if(pthread_cond_wait(&cond, &mutex) < 0){
printf("ERROR: pthread_cond_wait failed\n");
exit(1);
}
printf("Producer <%d> waiting\n", id);
}
//Put the number in the cb
cb_push_back(cb, &numbers[i]);
// printf("Producer <%d>: %d\n", id, numbers[i]);
fprintf(producer_file, "Producer <%d>: %d\n", id, numbers[i]);
count++;
//Count is a global variable to inform the consumers that there're
//no more numbers to be produced
//Tell the consumer threads that you have put a number to the cb
if(pthread_cond_broadcast(&cond) < 0){
printf("ERROR: pthread_cond_broadcast failed.\n");
exit(1);
}
//Unlock the mutex
if(pthread_mutex_unlock(&mutex) < 0){
printf("ERROR: pthread_mutex_unlock failed\n");
exit(1);
}
//printf("Producer thread <%d> unlocked mutex\n", *id);
}
// Free array
free(numbers);
//Close File
fprintf(producer_file, "-- END DATA --");
if( fclose(producer_file) != 0){
printf("ERROR: fclose failed.\n");
exit(1);
}
//THREAD EXIT
printf("PRODUCER %d EXITS\n", id);
pthread_exit(t);
}
And here is the consumer thread
void * newConsumer(void * t){
// Get the thread id
int * a = (int*) t;
int id = *a;
printf("Consumer thread %d started!\n", id);
int number;
//Open the file
FILE * consumer_file = fopen("cons_out.txt", "w");
if(consumer_file == NULL){
printf("ERROR: fopen failed.\n");
exit(1);
}
fprintf(consumer_file, "-- CONSUMER DATA --\n");
/*Consume integers until there are no integers left
either to be produced or in the buffer waiting */
while(count != p*n || cb->count != 0){
//Lock the mutex
//printf("Consumer <%d> has locked the mutex\n", *id);
if (pthread_mutex_lock(&mutex) < 0){
printf("ERROR: Could not lock mutex\n");
exit(1);
}
//Wait until a producer puts an integer in the cb
while(cb->count == 0 && end == 0){
printf("Consumer <%d> waiting\n", id);
if(pthread_cond_wait(&cond, &mutex) < 0){
printf("ERROR: pthread_cond_wait failed.\n");
exit(1);
}
}
if (cb->count != 0){
//Consume a number
cb_pop_front(cb, &number);
// printf("Consumer <%d>: %d\n", id, number);
fprintf(consumer_file, "Consumer <%d>: %d\n", id, number);
}
//Tell the producers that you have popped a number from the cb
if(pthread_cond_broadcast(&cond) < 0){
printf("ERROR: pthread_cond_broadcast() failed.\n");
exit(1);
}
//printf("Consumer <%d> Broadcast.\n", id);
//Unlock the mutex
//printf("Consumer <%d> has unlocked the mutex\n", *id);
if(pthread_mutex_unlock(&mutex) < 0){
printf("ERROR: pthread_mutex_unlock failed\n");
exit(1);
}
}
//Close the file stream
fprintf(consumer_file, "-- END DATA --");
if(fclose(consumer_file) != 0){
printf("ERROR: fclose failed.\n");
exit(1);
}
// THREAD EXIT
printf("CONSUMER %d EXITS\n", id);
pthread_exit(t);
}
In the main function i run
pthread_t * CONSUMERS[i] = (pthread_t*) malloc(sizeof(pthread_t) * i);
if (CONSUMERS == NULL){
printf("ERROR: Malloc failed.\n");
exit(1);
}
for (i = 0; i<c; i++){
id[i] = i+1;
pthread_create(&CONSUMERS[i], NULL, newConsumer, &id[i]);
}
and the I wait for them to finish.
i do exactly the same for the producer threads.( With a diffrent pthread_t array and id array.)
So the thing is : the id I put at the args at create is getting changed. If I run 5 consumer threads even though I put their id as 1 , 2, 3, 4, 5 it comes out as 65, 2, 3, 4, 68. This happens to the producer threads as well.
Thanks.

Related

Trying to pass a struct with 3 variables in a thread function which generates a sequence of random integers, to be placed in a circular buffer

This function is executed by a thread. I believe the error occurs when I try to access rand_count which, is a variable of the struct called args. Note that the problem is located in the for loop of the producer.
void* Producers(void* fargs) {
printf("I am Producer and I am not locked\n");
args* f_args=(args*) fargs;
rc = pthread_mutex_lock(&Mutex);
printf("I am Producer and I am locked\n");
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_lock() is %d\n", rc);
pthread_exit(&rc);
}
printf(" The ruler of all mutexes has passed from here and shall start creating random numbers\n");
for(int i=0; i < *f_args->rand_count; ++i) {
printf ( "Creating random number\n");
my_random =rand_r(f_args->seed)%255;
if(i==cb->capacity) {
printf(" Your producer king will now sleep\n");
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n", rc);
pthread_exit(&rc);
}
rc = pthread_cond_wait(&Condition, &Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n", rc);
pthread_exit(&rc);
}
}
cb_push_back(cb, &my_random);
if(i==0) {
fp=fopen("prod_in.txt", "w");
} else {
fp=fopen("prod_in.txt", "a");
}
fprintf(fp, "Producer %d: %d\n", f_args->ID, my_random);
}
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n", rc);
pthread_exit(&rc);
}
rc = pthread_mutex_unlock(&Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
pthread_exit(&rc);
}
}
This is the struct
typedef struct args{
int ID; //Unique ID from 1 to n
int* seed; //The seed used for rand_r
int* rand_count; //The number of random generated numbers
}args;

Thread function malfunctions, incomplete output and segmentation error

The following code is supposed to create one Producer thread and one Consumer thread. The Producer creates random numbers, adds them to a circular buffer(push_back()) and then writes them in an output txt called prod_out.txt. The Consumer "consumes" these numbers by poping them (pop_front()) and then writing them in an output txt called cons_out.txt. For a call like this ./a.out 1 1 10 20 1 the arguements are as follows: there will be 1 producer, 1 consumer, 10 is circular buffer's capacity, 20 random numbers will be generated and the seed for rand_r is 1.
If the buffer's capacity is smaller than the ammount of random nums to be generated the program only writes 9 numbers in the consumers' txt, while the producers' txt is just fine. If they are the same then the consumers' txt does not get created and producers' txt misses one number (namely the last one, just like the consumer txt does when the capacity is smaller than the numbers generated).
This is the main function
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "prodcons.h"
FILE * fp;
int rc;
circular_buffer* cb;
int fileW, my_random;
pthread_mutex_t Mutex;
pthread_cond_t Condition;
args* t_args;
void* Producers(void* fargs){
printf("I am Producer and I am not locked\n");
args* f_args= fargs;
rc = pthread_mutex_lock(&Mutex);
printf("I am Producer and I am locked\n");
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_lock() is %d\n", rc);
pthread_exit(&rc);
}
printf(" The ruler of all mutexes has passed from here and shall start
creating random numbers\n");
for(int i=0; i < *(f_args->rand_count); i++){
if(i==cb->capacity){
printf(" Your producer king will now sleep\n");
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n",
rc);
pthread_exit(&rc);
}
rc = pthread_cond_wait(&Condition, &Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n",
rc);
pthread_exit(&rc);
}
}
my_random =rand_r(f_args->seed)%255;
printf ( "Creating random number %d.\n", my_random);
cb_push_back(cb, &my_random);
if(i==0){
fp=fopen("prod_in.txt", "w");
}else{
fp=fopen("prod_in.txt", "a");
}
fprintf(fp, "Producer %d: %d\n", f_args->ID, my_random);
fclose(fp);
}
printf("I am going to go to signal the consumer.\n");
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n", rc);
pthread_exit(&rc);
}
rc = pthread_mutex_unlock(&Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
pthread_exit(&rc);
}
}
void* Consumer(void* t1){
int *threadId = (int *) t1;
printf("I am Consumer and I am NOT locked\n");
rc = pthread_mutex_lock(&Mutex);
printf("I am Consumer and I am locked\n");
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_lock() is %d\n", rc);
pthread_exit(&rc);
}
if(cb->count == 0){
rc = pthread_cond_wait(&Condition, &Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n", rc);
pthread_exit(&rc);
}
}
int counter = cb-> count;
for (int j=0; j<= counter; j++){
printf("Consumer will now consume with items remaining %d.\n", (int)cb-
>count);
if(j==0){
fp=fopen("cons_out.txt", "w");
}else{
fp=fopen("cons_out.txt", "a");
}
printf("I will now write the following %d, %d inside the
file.\n",*threadId,my_random);
fprintf(fp, "Consumer %d: %d\n",*threadId, my_random);
cb_pop_front(cb,&my_random);
if(cb->count == 0){
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n",
rc);
pthread_exit(&rc);
}
rc = pthread_cond_wait(&Condition, &Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n",
rc);
pthread_exit(&rc);
}
}
fclose(fp);
}
rc = pthread_mutex_unlock(&Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
pthread_exit(&rc);
}
}
int main(int argc, char *argv[]){
if (argc !=6){
printf("ERROR: the program should take five arguments!\n");
exit(-1);
}
if(atoi(argv[1])!= 1 || atoi(argv[2])!= 1){
printf("ERROR:This program only functions for one producer and
consumer.\n");
exit(-1);
}
int main_seed = atoi(argv[5]);
int main_rand = atoi(argv[4]);
int buffer_size = atoi(argv[3]);
cb=(circular_buffer*) malloc(sizeof(struct circular_buffer));
t_args=(args*)malloc(sizeof(struct args));
cb_init(cb, buffer_size, sizeof(int));
t_args->seed= &main_seed;
t_args->rand_count= &main_rand;
t_args->ID=1;
int t1=1;
pthread_t p1, c1;
printf ( "I am the ruler of all mutexes. I now shall initialise the
mutex\n");
rc = pthread_mutex_init(&Mutex, NULL);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_init() is %d\n", rc);
exit(-1);
}
rc = pthread_cond_init(&Condition, NULL);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_init() is %d\n", rc);
exit(-1);
}
rc = pthread_create(&p1, NULL, Producers, (void*)t_args); //cast σε void????
if (rc != 0) {
printf("ERROR: return code from pthread_create() is %d\n", rc);
exit(-1);
}
rc = pthread_create(&c1, NULL,Consumer, &t1);
if (rc != 0) {
printf("ERROR: return code from pthread_create() is %d\n", rc);
exit(-1);
}
void *status;
rc = pthread_join(p1, &status);
if (rc != 0) {
printf("ERROR: return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main(): Thread %d terminated successfully.\n", *(int *) status);
rc = pthread_join(c1, &status);
if (rc != 0) {
printf("ERROR: return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main(): Thread %d terminated successfully.\n", *(int *) status);
rc = pthread_mutex_destroy(&Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_destroy() is %d\n", rc);
exit(-1);
}
rc = pthread_cond_destroy(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_destroy() is %d\n", rc);
exit(-1);
}
free(cb);
free(t_args);
return 1;
}
This is a header file with the 2 structs and the circular buffer functions
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "string.h"
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
}circular_buffer;
typedef struct args
{
int ID; //Unique ID from 1 to n
int* seed; //The seed used for rand_r
int* rand_count; //The number of random generated numbers
}args;
void cb_push_back(circular_buffer *cb, const void *item);
void cb_pop_front(circular_buffer *cb, void *item);
void cb_init(circular_buffer *cb, size_t capacity, size_t sz);
void cb_free(circular_buffer *cb);
In this file are the implementetions of the circular buffer functions
#include "prodcons.h"
//initialize circular buffer
//capacity: maximum number of elements in the buffer
//sz: size of each element
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;
}
//destroy circular buffer
void cb_free(circular_buffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
}
//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++;
}
//remove first item from circular item
void cb_pop_front(circular_buffer *cb, void *item)
{
if(cb->count == 0)
{
printf("Access violation. Buffer is empy\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--;
}

C code stops after creating the first pthread (Linux)

My code should be executing the start_hydrogen and start_carbon functions several times but only outputs to the console from execution of one thread and then the program hangs. I think I may be incorrectly starting my threads. I am new to C so let me know if additional information is needed. Note that the this line is reached output is printed.
#include "main.h"
void *start_hydrogen(void *);//executes hydrogen.c
void *start_carbon(void *);//executes carbon.c
struct threadInfo {
int threadId;
};
struct threadInfo hydrogenIDs[NUM_H];
struct threadInfo carbonIDs[NUM_C];
int main() {
int semid, shmid;//semaphore memory id, shared memory id
unsigned short seminit[NUM_SEMS];//used to initialize semaphores
struct common *shared;//pointer to shared data structure
union semun semctlarg;//used to initialize semaphores
pthread_t hydrogen[NUM_H];
pthread_t carbon[NUM_C];
pthread_attr_t attr;
void *exit_status;
//Creating a set of attributes to send to the threads
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//get semaphore memory id
if ((semid = semget(SEMKEY, NUM_SEMS, IPC_CREAT|0777)) < 0) {
perror("semget");
exit(EXIT_FAILURE);
}
printf("THE PROGRAM IS STARTING\n\n");
seminit[MUTEX] = 1;//initialize mutex semaphore count to 1
seminit[SH] = 0;//initialize hyrdrogen semaphore count to 0
seminit[SC] = 0;//initialize carbon semaphore count to 0
semctlarg.array = seminit;//set control array
//apply initialization
if ((semctl(semid, NUM_SEMS, SETALL, semctlarg)) < 0) {
perror("semctl");
exit(EXIT_FAILURE);
}
//get shared memory id
if ((shmid = shmget(SHMKEY, 1*K, IPC_CREAT|0777)) < 0) {
perror("shmget");
exit(EXIT_FAILURE);
}
//retrieve pointer to shared data structure
if ((shared = (struct common *)shmat(shmid, 0, 0)) < 0) {
perror("shmat");
exit(EXIT_FAILURE);
}
//initialize shared data structure variables
shared->waiting_H = 0;
shared->waiting_C = 0;
int retVal;//used to check return value of fork()
// spawn 20 Hydrogens
for (int i=0; i<NUM_H; i++) {
// if ((retVal = fork()) == 0) {
// hydrogen();
// fflush(stdout);
// printf("New Hydrogen process created\n");
// fflush(stdout);
// } else if (retVal < 0) {
// perror("fork");
// exit(EXIT_FAILURE);
// }
hydrogenIDs[i].threadId = i;
retVal = pthread_create(&hydrogen[i], &attr, start_hydrogen, (void*) &hydrogenIDs[i]);
if (retVal != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
printf("this line reached\n");
// spawn 5 Carbons
for (int i=0; i<NUM_C; i++) {
// if ((retVal = fork()) == 0) {
// carbon();
// fflush(stdout);
// printf("New Hydrogen process created\n");
// fflush(stdout);
// } else if (retVal < 0) {
// perror("fork");
// exit(EXIT_FAILURE);
// }
carbonIDs[i].threadId = i;
retVal = pthread_create(&carbon[i], &attr, start_carbon, (void*) &carbonIDs[i]);
if (retVal != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
//wait for all car processes to finish
// for (int i = 0; i < 25; ++i) {
// if (wait(0) < 0) {
// perror("wait");
// exit(EXIT_FAILURE);
// }
// }
//Wait for all the threads to finish
for(int i = 0; i < NUM_C; i++)
{
pthread_join(carbon[i], &exit_status);
}
for(int i = 0; i < NUM_H; i++)
{
pthread_join(hydrogen[i], &exit_status);
}
printf("All atoms have crossed!\n");
//delete semaphores
if (semctl(semid, NUM_SEMS, IPC_RMID, 0) < 0) {
perror("semctl");
exit(EXIT_FAILURE);
}
//delete shared memory
if (shmctl(shmid, IPC_RMID, 0) < 0) {
perror("shmctl");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
Original start_carbon() and start_hydrogen() functions
void *start_carbon(void* arg) {
execl("carbon", "carbon", 0);
perror("execl");
exit(EXIT_FAILURE);//if exec returns there was an error
}
void *start_hydrogen(void* arg) {
execl("hydrogen", "hydrogen", 0);
perror("execl");
exit(EXIT_FAILURE);//if exec returns there was an error
}
Modified start_hydrogen() and start_carbon() functions
After receiving feedback about the inappropriateness of using execl(), I changed the start_hydrogen() and start_carbon() functions to:
void *start_hydrogen(void* arg) {
struct common *shared;//pointer to shared data structure
int semid, shmid;//semaphore memory id, shared memory id
int pid = getpid();
//get semaphore memory id
if ((semid = semget(SEMKEY, NUM_SEMS, 0777)) < 0) {
perror("semget");
exit(EXIT_FAILURE);
}
//get shared memory id
if ((shmid = shmget(SHMKEY, 1*K, 0777)) < 0) {
perror("shmget");
exit(EXIT_FAILURE);
}
//get pointer to shared data structure
if ((shared = (struct common *)shmat(shmid, 0, 0)) < 0) {
perror("shmat");
exit(EXIT_FAILURE);
}
// acquire lock on mutex before accessing shared memory
semWait(semid, MUTEX);
fflush(stdout);
printf("Hydrogen atom, pid %d, arrives at barrier\n", pid);
printf("Currently %d Hydrogens and %d Carbons waiting\n", shared->waiting_H + 1, shared->waiting_C);
fflush(stdout);
// if enough C and H is waiting, continue past barrier
if (shared->waiting_H >= 3
&& shared->waiting_C >= 1) {
// release 3 H
for (int i=0; i < 3; i++) {
semSignal(semid, SH);
}
shared->waiting_H -= 3;
semSignal(semid, SC); // release 1 C
shared->waiting_C -= 1;
fflush(stdout);
printf("\nHello from %d, 1 CH4 molecule has xed the barrier\n\n", pid);
fflush(stdout);
// release lock on mutex
semSignal(semid, MUTEX);
} else {
// not enough C or H is waiting, so wait at barrier
shared->waiting_H += 1;
// relaese lock on mutex
semSignal(semid, MUTEX);
semWait(semid, SH);
}
pthread_exit(NULL);
}
void *start_carbon(void* arg) {
struct common *shared;//pointer to shared data structure
int semid, shmid;//semaphore memory id, shared memory id
int pid = getpid();
//get semaphore memory id
if ((semid = semget(SEMKEY, NUM_SEMS, 0777)) < 0) {
perror("semget");
exit(EXIT_FAILURE);
}
//get shared memory id
if ((shmid = shmget(SHMKEY, 1*K, 0777)) < 0) {
perror("shmget");
exit(EXIT_FAILURE);
}
//get pointer to shared data structure
if ((shared = (struct common *)shmat(shmid, 0, 0)) < 0) {
perror("shmat");
exit(EXIT_FAILURE);
}
// acquire lock on mutex before accessing shared memory
semWait(semid, MUTEX);
fflush(stdout);
printf("Hydrogen atom, pid %d, arrives at barrier\n", pid);
printf("Currently %d Hydrogens and %d Carbons waiting\n", shared->waiting_H + 1, shared->waiting_C);
fflush(stdout);
// if enough C and H is waiting, continue past barrier
if (shared->waiting_H >= 3
&& shared->waiting_C >= 1) {
// release 3 H
for (int i=0; i < 3; i++) {
semSignal(semid, SH);
}
shared->waiting_H -= 3;
semSignal(semid, SC); // release 1 C
shared->waiting_C -= 1;
fflush(stdout);
printf("\nHello from %d, 1 CH4 molecule has xed the barrier\n\n", pid);
fflush(stdout);
// release lock on mutex
semSignal(semid, MUTEX);
} else {
// not enough C or H is waiting, so wait at barrier
shared->waiting_H += 1;
// relaese lock on mutex
semSignal(semid, MUTEX);
semWait(semid, SH);
}
pthread_exit(NULL);
}
From the man page for execl(),
The exec() family of functions replaces the current process image with a new process image.
and
The exec() functions only return if an error has occurred.
If you want to use execl() to call external programs, you should fork() the parent process first to allow the parent process to continue running. Note in that case, the threads really won't do what you want.

Reader is not reading from a shared memory

I'm reading from a file and then write it on a shared memory.But the Writer is writing in a shared memory is working fine but reader is not reading from a shared memory. maxlen[x] have stored a maximum length of a line.
void * reader (void * param){
int i;
int count=1;
int waittime;
waittime = rand() % 5;
sleep(waittime);
shm_ptr = shmat(shm_id, NULL, 0);
if ((int)shm_ptr == -1){
printf("*** shmat error (server) ***\n");
exit(1);
}
sleep(1);
printf("\nReader is trying to enter");
sem_wait(&mutex);
readcount++;
if(readcount==1)
sem_wait(&wrt);
printf("\n%d Reader is inside ",readcount);
printf(" in crtical section \n");
int sizes=x;
x=0;
while (x<=sizes) {
shm_ptr[x] = malloc( sizeof(char *)* maxlen[x]);
puts(shm_ptr[x]);
x++;
}
sem_post(&mutex);
sem_wait(&mutex);
readcount--;
if(readcount==0)
sem_post(&wrt);
sem_post(&mutex);
printf("\nReader is Leaving");
sleep(waittime);
}

Problems with shared buffer and synchronized programming

I just started learning how to mess with threads and synchronized programming in C. I'm trying to code a reader which uses threads (POSIX interface) to read selected files from a shared buffer. The children threads will retrieve the file names from the buffer, while the father thread will be infinitly reading filenames from stdin and placing them in the buffer. What am I doing wrong?
pthread_mutex_t lock;
static char* files[NFILES];
int top = NFILES-1;
void putInBuffer(char* file){
pthread_mutex_lock(&lock);
if(top < NFILES-1){
files[top] = file;
top++;
}
pthread_mutex_unlock(&lock);
}
char* removeFromBuffer(){
char* file;
pthread_mutex_lock(&lock);
file = files[top];
top--;
pthread_mutex_unlock(&lock);
return file;
}
void* leitor(){
int op,i,r,cl;
char* file;
char buff[NCHARS];
char teste[NCHARS];
while(1){
pthread_mutex_lock(&lock);
file = removeFromBuffer();
printf("%s\n", file);
op = open(file, O_RDONLY);
if(op == -1) {
perror("Open unsuccessful");
pthread_exit((void*)-1);
}
r = read(op, teste, NBYTES);
if(r == -1){
perror("Read unsuccessful");
pthread_exit((void*)-1);
}
for(i=0; i<NLINES-1; i++){
r = read(op, buff, NBYTES);
if(r == -1){
perror("Read unsuccessful");
pthread_exit((void*)-1);
}
if(strcmp(buff,teste) != 0){
perror("Incorrect file");
pthread_exit((void*)-1);
}
}
cl = close (op);
if(cl == -1){
perror("Close unsuccessful");
pthread_exit((void*)-1);
}
printf("Correct file: %s\n", file);
pthread_mutex_unlock(&lock);
}
pthread_exit((void*)0);
return NULL;
}
int main(){
pthread_t threads[NTHREADS];
int i,*status;
char file[LENFILENAME];
if (pthread_mutex_init(&lock, NULL))
{
perror("\n mutex init failed\n");
exit(-1);
}
for(i=0;i<NTHREADS;i++){
if(pthread_create(&(threads[i]),NULL, leitor,NULL)){
perror("Failed to create thread");
exit(-1);
}
}
while(1){
read(STDIN_FILENO, file, LENFILENAME);
printf("%s\n", file);
putInBuffer(file);
printf("%s\n", removeFromBuffer());
}
for (i=0;i<NTHREADS;i++){
if(pthread_join(threads[i],(void**)&status)){
perror("Failed to join thread");
exit(-1);
}
printf("Thread returned %d\n", status);
}
pthread_mutex_destroy(&lock);
return 0;
}
Given what your program is doing, it seems that you should use a separate semaphore for notifying the child threads of new input instead of using the mutex that you have created.
Each child thread should wait on the semaphore at the top of the while loop, where you currently have pthread_mutex_lock(). After the parent has finished putInBuffer, it should release the semaphore once. When a child thread grabs the semaphore, it can call removeFromBuffer to get the next file, and read it (i.e. what you have already written). After the child finishes with the file, it should not release the semaphore, just go back to the top of the loop and wait on it again.
You have correctly used the mutex in putInBuffer and removeFromBuffer to protect accesses to the shared variables files and top.

Resources