Hi i want to implement a client-server program that communicates with each other via shared memory.
in the server side i have two threads. a writer thread and a reader thread. the writer thread puts some data into the queue and the reader thread reads from it and passes the data to the client side via shared memory.each client that has shmid can attach itself to it and read data from it...
right now i get segmentation fault at client side when it comes to attach to shared memory.
here is my code:
server side:
typedef struct shared_mem {
char imgDir[100];
int client_id;
int read_client;
sem_t shm_sem;
}shared_mem;
shared_mem *shared;
int main(int argc , char *argv[])
{
pthread_t writer_t, reader_t;
queue_t = (struct Queue*) malloc(sizeof(Queue));
queue_t->head = 0;
queue_t->tail = 0;
sem_init(&queue_t->empty, 0, QUEUE_SIZE);
sem_init(&queue_t->full, 1, 0);
int shmid;
key_t key;
key =3434;
//Create the segment and set permissions.
if ((shmid = shmget(key, sizeof(struct shared_mem), IPC_CREAT | 0666)) < 0)
{
perror("shmget error");
if(errno==EEXIST)
{
fprintf(stderr,"shared memory exist... ");
exit(1);
}
}
fprintf(stdout,"shared mem created with id: %d\n",shmid);
if( pthread_create( &reader_t , NULL , reader_thread , &shmid) < 0)
{
perror("could not create reader thread");
return 1;
}
puts("reader thread assigned");
if( pthread_create( &writer_t , NULL , writer_thread , NULL) < 0)
{
perror("could not create writer thread");
return 1;
}
puts("writer thread assigned");
pthread_join(reader_t, NULL);
pthread_join(writer_t, NULL);
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
//---------
void *reader_thread(void * id)
{
char imgPath[100];
FILE *image_fd;
char * img_filename;
char imgBuf[1024];
int readed_img_data;
char imgcount[10];
char * shm_addr;
int shm_id = *((int *)id);
shared = (struct shared_mem *) shmat(shm_id, NULL, 0);
if ((int) shared == -1)
{
printf("*** shmat error (server) ***\n");
exit(1);
}
memset(shared, 0, sizeof(struct shared_mem));
sem_init(&shared->shm_sem, 1, 1);
shared->read_client = 0;
shared->client_id = 1;
//printf("shared address: %s", &shared);
while (1)
{
printf("Here in thread reader!\n");
sem_wait(&queue_t->full);
sem_wait(&shared->shm_sem);
if (queue_t->tail != queue_t->head)
{
memmove(imgPath,queue_t->imgAddr[queue_t->head],strlen(queue_t->imgAddr[queue_t->head])-1);
imgPath[strlen(queue_t->imgAddr[queue_t->head])-1] = '\0';
queue_t->head = (queue_t->head + 1) % QUEUE_SIZE;
}
sem_post(&queue_t->empty);
printf("imagepath size: %d...\n",sizeof(imgPath));
memcpy(&shared->imgDir, &imgPath, sizeof(imgPath));
printf("shared contents: %s\n",(char *) &shared->imgDir);
shared->read_client = 0;
sem_post(&shared->shm_sem);
} //end while
if(shmdt(shm_addr) != 0)
fprintf(stderr, "Could not close memory segment.\n");
return 0;
}
clientSide():
typedef struct shared_mem {
char imgDir[100];
int client_id;
int read_client;
sem_t shm_sem;
}shared_mem;
shared_mem *shared;
int main(int argc , char *argv[])
{
char server_data[1024];
int server_data_len = 1024;
char imgDir[100]= "client_/"; // directory where client store image
char imgPath[100]; // image address which client pop from shared memory
char *imgFilename;
char imgcount[10] = "";
int readed_img_data;
int shmid;
key_t key;
key = 3434;
shmid = shmget(key, sizeof(struct shared_mem), 0666);
printf("get shmid: %d\n ", shmid);
if ((shared = (struct shared_mem *) shmat(shmid, NULL, 0)) == (void *) -1)
{
perror("shmat error");
return 1;
}
shared->client_id = 0;
sprintf(imgDir,"%s", shared->imgDir);
//keep communicating with server
while(1)
{
printf("\nReceiving new file...\n");
sem_wait(&shared->shm_sem);
memcpy(&imgPath, &shared->imgDir, 100);
memcpy(&read_client, &shared->read_client, 4);
if (read_client == 0)
read_client = 1;
memcpy(&shared->read_client, &read_client, 4);
sem_post(&shared->shm_sem);
FILE * Client_img = fopen(imgPath,"r");
if (!Client_img)
printf("%s not created!", imgPath);
fseek(Client_img, 0, SEEK_END); // seek to end of file
long size = ftell(Client_img); // get current file pointer
rewind(Client_img);
printf("size: %ld", size);
imgFilename= strrchr(imgPath,'/');
if(imgFilename)
++imgFilename;
else
{
imgFilename = (char*)malloc(100 * sizeof(char));
memmove(imgFilename,imgPath, strlen(imgPath));
}
strcat(imgDir, imgFilename);
printf("imgDir:%s", imgDir);
FILE * written_img = fopen(imgDir, "wa");
int read_sz = fread(server_data, sizeof(char), size, Client_img);
int write_sz = fwrite(server_data, sizeof(char), read_sz, written_img);
fclose(Client_img);
fclose(written_img);
}//while
if(shmdt(shm) != 0)
fprintf(stderr, "Could not close memory segment.\n");
return 0;
}
Related
I am writing a producer/consumer app where one thread writes to the message queue while other consumes/reads from it, but it seems as if both the mq_send() and mq_receive() are blocked hence no transmission takes place.
In other words, I don't see the prints from either Transmit or Receive functions i.e Received buffer: %s or Sent...
#define MAX_MESSAGES 10
#define MAX_BUFF_SIZE 180
#define MSG_BUFF_SIZE MAX_BUFF_SIZE + 10
#define QUEUE_PERMISSIONS 0660
static pthread_t rxHdlr;
static pthread_t txHdlr;
static void* Transmit(void* arg);
static void* Receive(void* arg);
char readBuffer [MSG_BUFF_SIZE];
char writeBuffer [MSG_BUFF_SIZE];
#define NAME "/sp-sample"
int main(int argc, char* argv[])
{
if (pthread_create(&rxHdlr, NULL, Receive, NULL) != 0)
{
printf("Fail to create a server thread!\n");
}
if (pthread_create(&txHdlr, NULL, Transmit, NULL) != 0)
{
printf ("fail to create a client thread\n");
}
pthread_join(rxHdlr, 0);
pthread_join(txHdlr, 0);
}
Consumer
static void* Receive(void* arg)
{
struct mq_attr attr;
static mqd_t mqd;
attr.mq_flags = 0;
attr.mq_maxmsg = MAX_MESSAGES;
attr.mq_msgsize = MAX_BUFF_SIZE;
attr.mq_curmsgs = 0;
mq_unlink(NAME);
if ((mqd = mq_open (NAME, O_RDONLY | O_CREAT, 0644, &attr)) == -1)
{
printf ("mq_open failed in UartRx: %s\n", strerror(errno));
exit (1);
}
while(1)
{
int iret = mq_receive(mqd, readBuffer, sizeof(readBuffer), NULL);
if (iret == -1)
{
printf ("Errno: %d\n", errno);
}
printf ("Received buffer: %s\n", readBuffer);
}
}
Producer
static void* Transmit(void* arg)
{
int iRet;
mqd_t mqd;
char buffer[100] = "TX data!";
if ((mqd = mq_open (NAME, O_WRONLY)) == -1)
{
printf ("TX MqOpen failed - %s\n", strerror(errno));
exit (1);
}
while(1)
{
if (mq_send (mqd, buffer, strlen (buffer) + 1, 0) == -1)
{
perror ("Client unable to send message to server");
}
printf ("Sent...\n");
}
}
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.
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.
I have a program where I want to set up a pointer to a struct as shared memory. I think I've set up the shared memory correctly in the main method; then I call a function to initialize the struct, and fork. However, the child process can't access the shared memory; the parent process works as expected, which isn't that big of a surprise. I know for sure that the child process executes and works, but it cannot access the shared memory, so the function doesn't really do much besides print out printf statements.
struct OverSharedData{
struct SharedData ** rep;
int rop;
};
void initialize( struct OverSharedData * bill){
bill->rep = (struct SharedData**)malloc(sizeof(struct SharedData*)*consumerthreads);
int on =0;
for (on=0; on<consumerthreads; on++) {
*(bill->rep+on) = (struct SharedData *)malloc(sizeof(struct SharedData));
init(*(bill->rep + on), on); //
}}
int main(int argc, const char * argv[])
{
databases(argv[1]); /* Takes care of setting up the database*/
categories(argv[2]); /*Takes care of setting up the book categories*/
bookorders = argv[3];
key_t key = ftok("garbage.txt", 71);
int eyedee = shmget(key, sizeof(struct OverSharedData ),
IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (eyedee == -1)
{
perror("shmget");
exit(1);
}
struct OverSharedData *remp = (struct OverSharedData *) shmat(eyedee, 0, 0);
if (remp == (void *) -1)
{
perror("shmat");
exit(1);
}
initialize(remp);
struct SharedData * d = *(remp->rep + 0);
printf("Hallo\n");
shmctl(eyedee, IPC_RMID, 0);
pid_t forkk = fork();
if (forkk==0) {
/*THIS DOES NOT WORK*/
printf("Entered consumer check: %d\n", remp->rop);
int z = 0;
pthread_t Consumer_Threads[consumerthreads];
for (z=0; z<consumerthreads; z++) {
remp->rop = z;
d = *(remp->rep + z);
d->da = z;
pthread_create((Consumer_Threads+z), 0, Consumer, d);
}
for (z = 0; z<consumerthreads; z++) {
pthread_join(Consumer_Threads[z], NULL);
}
shmdt(remp);
}
else{
/*THIS WORKS*/
printf("Entered Producer: %d\n",remp->rop);
pthread_t Produc;
pthread_create(&Produc, 0, Producer, remp);
pthread_join(Produc, NULL);
printf("Hey guys: %d\n", remp->rop);
shmdt(remp);
}
My guess is that I didn't initialize the struct correctly, but I'm not all too clear what I'm doing wrong. I left out some of the other initializing code but I figured since I can't even access the int in the OverSharedData struct, it's more of a matter where I can't access the struct in the first place.
The problem is that your shared data (the single OverSharedData object) contains pointers to non-shared data. You need to allocate all the data that you want shared in the shared memory segment, rather than with malloc. Something like:
static void *shared_available;
static size_t shared_left;
void init_shared(size_t size) {
key_t key = ftok("garbage.txt", 71);
int eyedee = shmget(key, size,
IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (eyedee == -1) {
perror("shmget");
exit(1); }
shared_available = shmat(eyedee, 0, 0);
if (shared_available == (void *) -1) {
perror("shmat");
exit(1); }
shared_left = size;
}
void *alloc_shared(size_t size) {
void *rv = shared_available;
if (size > shared_left) {
fprintf(stderr, "Ran out of shared memory!\n");
exit(1); }
shared_available = (char *)rv + size;
shared_left -= size;
return rv;
}
OverSharedData *initialize() {
init_shared(sizeof(struct OverSharedData) +
sizeof(struct SharedData *) * consumerthreads +
sizeof(struct SharedData) * consumerthreads)
OverSharedData *bill = alloc_shared(sizeof(OverSharedData));
bill->rep = alloc_shared(sizeof(struct SharedData*)*consumerthreads);
for (int on=0; on<consumerthreads; on++) {
bill->rep[on] = alloc_shared(sizeof(struct SharedData));
init(&bill->rep[on], on); }
}
The above will still have problems if the init routine tries to store pointers to non-shared memory into the SharedData struct (you don't show the definition of either, so we can't say).
If you want to be able to more flexibly allocate and manage shared memory across processes, you really need to use a general purpose shared memory allocator/manager, such as this
I am trying to implement something that will give me a solution for:
| --> cmd3 --> cmd4 -->
cmd2-->|
| --> cmd5 --> cmd6 -->
and so on...
This is multiple executions of processes and pipe the results via chains of other's processes with threads, each commands chain should run in different thread.
I choose socketpair for the implementation of IPC, because pipe has a a bottleneck with the buffer size limit 64K.
When I test the program with single chain - it's work as expected, but when I am running master command and the output of it I send via socketpair to read end of multiple processes in each thread - the program stuck (look like a deadlock)
Whats I am doing wrong:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/socket.h>
typedef struct command {
char** argv;
int num_children;
struct command* master_cmd;
struct command** chains;
struct command* next;
int fd;
} command;
void be_child(command* cmd);
int execute_master_command_and_pipe_to_childs(command* cmd, int input);
int run_pipeline_sockets(command *cmd, int input);
void waitfor(int fd);
int main(int argc, char* argv[]) {
handle_segfault();
command* cmd1 = (command*) malloc(sizeof(command));
command* cmd2 = (command*) malloc(sizeof(command));
command* cmd3 = (command*) malloc(sizeof(command));
command* cmd4 = (command*) malloc(sizeof(command));
command* cmd5 = (command*) malloc(sizeof(command));
command* cmd6 = (command*) malloc(sizeof(command));
command* chains1[2];
chains1[0] = cmd3;
chains1[1] = cmd5;
char* args1[] = { "cat", "/tmp/test.log", NULL };
char* args3[] = { "sort", NULL, NULL };
char* args4[] = { "wc", "-l", NULL };
char* args5[] = { "wc", "-l", NULL };
char* args6[] = { "wc", "-l", NULL };
cmd1->argv = args1;
cmd2->argv = NULL;
cmd3->argv = args3;
cmd4->argv = args4;
cmd5->argv = args5;
cmd6->argv = args6;
cmd1->master_cmd = NULL;
cmd1->next = NULL;
cmd1->chains = NULL;
cmd1->num_children = -1;
cmd2->master_cmd = cmd1;
cmd2->chains = chains1;
cmd2->next = NULL;
cmd2->num_children = 2;
cmd3->master_cmd = NULL;
cmd3->next = cmd4;
cmd3->chains = NULL;
cmd3->num_children = -1;
cmd4->master_cmd = NULL;
cmd4->next = NULL;
cmd4->chains = NULL;
cmd4->num_children = -1;
cmd5->master_cmd = NULL;
cmd5->next = cmd6;
cmd5->chains = NULL;
cmd5->num_children = -1;
cmd6->master_cmd = NULL;
cmd6->next = NULL;
cmd6->chains = NULL;
cmd6->num_children = -1;
int rc = execute_master_command_and_pipe_to_childs(cmd2, -1);
return 0;
}
int execute_master_command_and_pipe_to_childs(command* cmd, int input) {
int num_children = cmd->num_children;
int write_pipes[num_children];
pthread_t threads[num_children];
command* master_cmd = cmd->master_cmd;
pid_t pid;
int i;
for (i = 0; i < num_children; i++) {
int new_pipe[2];
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, new_pipe) < 0) {
int errnum = errno;
fprintf(STDERR_FILENO, "ERROR (%d: %s)\n", errnum,
strerror(errnum));
return EXIT_FAILURE;
}
if (cmd->chains[i] != NULL) {
cmd->chains[i]->fd = new_pipe[0];
if (pthread_create(&threads[i], NULL, (void *) be_child,
cmd->chains[i]) != 0) {
perror("pthread_create"), exit(1);
}
write_pipes[i] = new_pipe[1];
} else {
perror("ERROR\n");
}
}
if (input != -1) {
waitfor(input);
}
int pipefd = run_pipeline_sockets(master_cmd, input);
int buffer[1024];
int len = 0;
while ((len = read(pipefd, buffer, sizeof(buffer))) != 0) {
int j;
for (j = 0; j < num_children; j++) {
if (write(write_pipes[j], &buffer, len) != len) {
fprintf(STDERR_FILENO, "Write failed (child %d)\n", j);
exit(1);
}
}
}
close(pipefd);
for (i = 0; i < num_children; i++) {
close(write_pipes[i]);
}
for (i = 0; i < num_children; i++) {
if (pthread_join(threads[i], NULL) != 0) {
perror("pthread_join"), exit(1);
}
}
}
void waitfor(int fd) {
fd_set rfds;
struct timeval tv;
int retval;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 500000;
retval = select(fd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1)
perror("select()");
else if (retval) {
printf("Data is available now on: %d\n", fd);
} else {
printf("No data on: %d\n", fd);
///waitfor(fd);
}
}
void be_child(command* cmd) {
printf(
"fd = %d , argv = %s , args = %s , next = %d , master_cmd = %d , next_chain = %d\n",
cmd->fd, cmd->argv[0], cmd->argv[1], cmd->next, cmd->master_cmd,
cmd->chains);
waitfor(cmd->fd);
int fd = run_pipeline_sockets(cmd, cmd->fd);
waitfor(fd);
int buffer[1024];
int len = 0;
while ((len = read(fd, buffer, sizeof(buffer))) != 0) {
write(STDERR_FILENO, &buffer, len);
}
close(cmd->fd);
close(fd);
}
int run_pipeline_sockets(command *cmd, int input) {
int pfds[2] = { -1, -1 };
int pid = -1;
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pfds) < 0) {
int errnum = errno;
fprintf(STDERR_FILENO, "socketpair failed (%d: %s)\n", errnum,
strerror(errnum));
return EXIT_FAILURE;
}
if ((pid = fork()) == 0) { /* child */
if (input != -1) {
dup2(input, STDIN_FILENO);
close(input);
}
if (pfds[1] != -1) {
dup2(pfds[1], STDOUT_FILENO);
close(pfds[1]);
}
if (pfds[0] != -1) {
close(pfds[0]);
}
execvp(cmd->argv[0], cmd->argv);
exit(1);
} else { /* parent */
if (input != -1) {
close(input);
}
if (pfds[1] != -1) {
close(pfds[1]);
}
if (cmd->next != NULL) {
run_pipeline_sockets(cmd->next, pfds[0]);
} else {
return pfds[0];
}
}
}
void segfault_sigaction(int signal, siginfo_t *si, void *arg) {
printf("Caught segfault at address %p\n", si->si_addr);
printf("Caught segfault errno %p\n", si->si_errno);
exit(0);
}
void handle_segfault(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sigaction));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = segfault_sigaction;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
}
I would come at this problem from a very different angle: rather than coming up with a large data structure to manage the pipe tree, and using threads (where an io blockage in a process may block in its threads) I would use only processes.
I also fail to see how a 64K buffer is your bottleneck when you're only using a 1K buffer.
2 simple functions should guide this: (error handling omitted for brevity, and using a pseudocodey parsecmd() function which turns a space separated string into an argument vector)
int mkproc(char *cmd, int outfd)
{
Command c = parsecmd(cmd);
int pipeleft[2];
pipe(pipeleft);
if(!fork()){
close(pipeleft[1]);
dup2(pipeleft[0], 0);
dup2(outfd, 1);
execvp(c.name, c.argv);
}
close(pipeleft[0]);
return pipeleft[1];
}
Mkproc takes the fd it will write to, and returns what it will read from. This way chains are really easy to initalize:
int chain_in = mkproc("cat foo.txt", mkproc("sort", mkproc("wc -l", 1)));
the next is:
int mktree(char *cmd, int ofd0, ...)
{
int piperight[2];
pipe(piperight);
int cmdin = mkproc(cmd, piperight[1]);
close(piperight[1]);
if(!fork()){
uchar buf[4096];
int n;
while((n=read(piperight[0], buf, sizeof buf))>0){
va_list ap;
int fd;
va_start(ap, ofd0);
for(fd=ofd0; fd!=-1; fd=va_arg(ap, int)){
write(fd, buf, n);
}
va_end(ap);
}
}
return cmdin;
}
Between the two of these, it is very easy to construct trees of arbitrary complexity, as so:
int tree_in = mktree("cat foo.txt",
mktree("rot13",
mkproc("uniq", mkproc("wc -l", 1)),
mkproc("wc -l", open("out.txt", O_WRONLY)), -1),
mkproc("sort", 2), -1);
This would output a sorted foo.txt to stderr, the number of lines in rot13'd foo.txt to out.txt, and the number of non-duplicate lines of rot13'd foo.txt to stdout.