Trying to implement the critical section of this program to actually swap between both threads correctly as stated later in the description.
I am trying to do a problem for my Operating Systems course. The problem is that I need to input two files, one of each are put into their separate threads, they will read through the file till they hit a line with the number "0". Then the other thread is supposed to run by the same rules.
This program is supposed to take two file input and figure out the message by concatenating both of the inputs from the files in a specific order and then printing out the output after it has deciphered it.
The inputs of these two files as shown below
Person1 Person2
--------- ----------
t 0
0 h
i 0
s 0
0 i
0 s
0 a
t 0
e 0
0 s
t 0
the above inputs should result in a string with this output
Example: “thisisatest”
Currently what is going wrong with the assignment is that it is not swapping correctly between the two threads and sitting in infinite loops.
Like I said above I am trying to solve this assignment by use of Mutexes and Pthreads
Below is the current implementation of my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static char *charArray[1000];
void *threadPerson1(void *value){
FILE *fPTR;
char buffer[2];
char *fileName = "Person1.txt";
fPTR = fopen(fileName, "r");
if (fPTR == NULL){
printf("was unable to open: %s\n", fileName);
return NULL;
}
while(1){
//Entering the critical section
pthread_mutex_lock(&mutex);
fscanf(fPTR, "%s", buffer);
printf("This is Person1: %s\n", buffer);
if(buffer != "0"){
charArray[count] = buffer;
count++;
}
if(buffer == "0"){
pthread_mutex_unlock(&mutex);
}
//exiting the critical section
}
}
void *threadPerson2(void *value){
FILE *fPTR;
char buffer[2];
char *fileName = "Person2.txt";
fPTR = fopen(fileName, "r");
if (fPTR == NULL){
printf("was unable to open: %s\n", fileName);
return NULL;
}
while(1){
//entering the critical section
pthread_mutex_lock(&mutex);
fscanf(fPTR, "%s", buffer);
printf("This is Person2: %s\n", buffer);
if(buffer != "0"){
charArray[count] = buffer;
count++;
}
if(feof(fPTR)){
printf("read end of file of: Person2\n");
fclose(fPTR);
return NULL;
}
if(buffer == "0"){
pthread_mutex_unlock(&mutex);
}
//exiting the critical section
}
}
int main(int argc, char **argv){
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, threadPerson1, NULL);
pthread_create(&thread2, NULL, threadPerson2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
for(int x = 0; x < 1000; x++){
if(charArray[x] == NULL){
printf("\n");
break;
}else{
printf("%s", charArray[x]);
}
}
return 0;
}
At least two things are incorrect in your program. First of all, if one thread releases the mutex, you are not guaranteed that the scheduler will allow the other thread will run, the releasing thread may very well go on and reacquire the mutex right away. Use a condition variable, read its manpages. Also, here are some examples, in particular 4-8: Multithreaded programming guide
Two, when you reach end of file, you need to release the mutex to clean up. Easiest way to do it is what we call RAII in C++, i.e. use a resource handle that releases the mutex when the handle object goes out of scope. You can do similar things in C e.g. by registering a cleanup function, or a 'goto' to end of function with cleanup code called from there.
Related
i m trying to implement the producer - consumer with threads.In my code below is working well except of the point where i try to print into 2 files.(one for prod and one for cons).I use fclose(stdout) . when i delete it inside producer then the print in producer file is ok but consumers no.when i deleted at all then all of the data printed into the consumer file.My question is what i should try to make the prints correctly( i need consumer to print in cons.out.txt and producer in prod_out.txt) .Also i didnt include check for threads to make it simple but it works well.
#include "head.h"
circular_buffer cb;
pthread_mutex_t lock;
pthread_cond_t cond;
char * data[6]; //is the data taken from cmd(argv[0-6]) first one is the program the other are parameters
int main(int argc , char *argv[]) {
validate(argv,argc); //if command arguments are valid go on
for(int i=0; i < argc; i++){
data[i]=argv[i]; //copy argv array to data array
}
cb_init(&cb,10,sizeof(int)); //initialization of circular buffer for 10 nodes + size of int each node
pthread_t cons, prod;
void *consumer(), *producer();
int rc = pthread_mutex_init(&lock, NULL);
rc = pthread_cond_init(&cond, NULL);
int id[]={1,2}; //prod id is 1 and cons 2
rc = pthread_create(&prod, NULL, producer, &id[0]);
rc = pthread_create(&cons, NULL, consumer, &id[1]);
rc=pthread_join(prod, NULL);
rc=pthread_join(cons, NULL);
rc = pthread_mutex_destroy(&lock);
rc = pthread_cond_destroy(&cond);
cb_free(&cb); //free allocated memory which is alocated in head
return 1;
}
void *consumer(void * id){
int thread_id= *((int*)id); //cast to (int)
int file;
FILE * fp2 = fopen("./cons_out.txt","wb"); //creates new file with "cons_out.txt" name
int i =10;
while(i > 0){
i--;
pthread_mutex_lock(&lock);
while(isEmpty(&cb)){
int rc = pthread_cond_wait(&cond,&lock);
}//end while
int item=0; // item that will be consumed
cb_pop_front(&cb,&item);
file = open("./cons_out.txt", O_APPEND | O_WRONLY, 0777 );//open file as new
if( file == -1 ) {//fail to open file
perror("./cons_out.txt");
return EXIT_FAILURE;
}
fclose(stdout);
dup2( file, STDOUT_FILENO); //change redirections
printf("Consumer %d : %d\n",thread_id,item); //print output to file
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
} //end while
return NULL;
} //end consumer()
void *producer(void * id){
int thread_id= *((int*)id); //cast to (*int)
int file1;
FILE * fp1 = fopen("./prod_in.txt","wb"); //creates new file with "prod_in.txt" name
for(int i=0; i<10; i++){ //it produce 10 numbers
pthread_mutex_lock(&lock);
while(isFull(&cb)){
int rc = pthread_cond_wait(&cond,&lock);
}//end while
int seed=1;
int item=rand(); // item of this producer
cb_push_back(&cb,&item);
file1 = open("./prod_in.txt", O_APPEND | O_WRONLY, 0777 );//open file as new
if( file1 == -1 ) {//fail to open file
perror("./prod_in.txt");
return EXIT_FAILURE;
}
fclose(stdout);
dup2( file1, STDOUT_FILENO); //change output
printf("Producer %i : %i\n",thread_id,item); //print output to file
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
} //end for
return NULL;
} //end Producer();
There is only one open file table for your whole process, shared by all threads in it. There is one entry in that table for the standard output, and your producer and consumer are contending for it. It's not clear why.
I'm inclined to think that the immediate reason for your troubles is that fclose()ing the stdout stream releases the stream-level resources, especially the buffer and state-tracking details. open()ing a file descriptor does not provide those, nor does dup2()ing a file descriptor into a FILE object representing a closed stream.
But it baffles me why you are making it so hard. Why in the world muck with duping file descriptors? Your producer and consumer already fopen() the wanted output files, thereby each obtaining its own stream connected with the appropriate file (fp1 and fp2). It seems to me that all you need to do, then, is to write to those streams via fprintf(), etc., instead of going to a lot of trouble to be able to use printf() instead.
That would be more efficient, too, since you oughtn't to need to keep opening and closing the files. Open each once, at the beginning, as you already do, and close each once, at the end, which you presently fail to do.
I am using multiple threads to access various random files using threads. However, I get an error [Thread 0x7ffff7007700 (LWP 16256) exited]. Also, info threads shows that only 2 threads are created. However, I am trying to create 100 of them. Also, do I have to use the pthread_join() function in my case? The code:
#define NTHREADS 100
void *encrypt(void *args)
{
int count = *((int*) args);
AES_KEY enc_key;
AES_set_encrypt_key(key, 128, &enc_key);
int i;
for(i=1;i<=count;i++){
char *ifile;
char *ofile;
long length;
size_t result;
char * buffer;
sprintf(ifile,"random_files/random_%d.txt",i);
FILE *ifp = fopen(ifile,"rb");
if (ifp==NULL) {fputs ("File error",stderr); exit (1);}
fseek(ifp,0, SEEK_END);
length = ftell(ifp);
fseek (ifp,0, SEEK_SET);
buffer = (char*) malloc (sizeof(char)*length);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
result = fread (buffer, 1, length, ifp);
if (result != length) {fputs ("Reading error",stderr); exit (3);}
printf("%s",buffer);
fclose (ifp);
free(buffer);
}
}
int main(){
int i,j,count =0;
pthread_t threads[NTHREADS];
for (i=0; i<NTHREADS; i++){
count = count +20;
int *count_ptr = &count;
if(pthread_create(&threads[i], NULL, encrypt, count_ptr)!=0){
fprintf(stderr, "error: Cannot create thread # %d\n", i);
break;
}
}
printf("After Thread\n");
exit(0);
}
Yes, you should join your threads, as none were created detached (and you're probably not deep enough in learning pthreads to deal with that anyway).
That said, you have a significant logic problem in your thread parameters. They're all getting the address of the same count variable in main. Probably the fastest way to change that with no modifications to your thread-proc is simply stand up a side-by-side array of int counts[NTHREADS] matching your threads, using each element as the corresponding thread's data param:
int main()
{
pthread_t threads[NTHREADS];
int counts[NTHREADS]; // HERE
int i,j,count =0;
for (i=0; i<NTHREADS; i++)
{
counts[i] = (count += 20);
if(pthread_create(&threads[i], NULL, encrypt, counts+i)!=0) // LAST PARAM
{
fprintf(stderr, "error: Cannot create thread # %d\n", i);
break;
}
}
for (i=0; i<NTHREADS; ++i)
pthread_join(threads[i], NULL));
return EXIT_SUCCESS;
}
Alternatively, you could do some dynamic allocation hoops, or send the value via intptr_t, cast to void*, but the method shown above has the advantage of requiring no changes on your thread-proc, a target I was aiming for.
I've left any issues in your thread proc to you to solve, but that should get you up and running on your thread stack, at least.
There are missing things in the code, first, in your encrypt function you need to close the threads at the end and also in the main function BUT, before you do so, after your for loop you need to join them all, then they are going to be processed and closed correctly.
The flow will go like this:
(void) pthread_join(th1, NULL);
(void) pthread_join(th2, NULL);
You can put them all in a for to join them by tid.
Another update: There is not really anything "random" going on, I would just start open the files according to its tid, and then add other big implementations, your as is will try to open files like crazy, it should work anyways but, just saying.
Whenever I run my code I get through 4 iterations of reading the file and creating a pthread until it segfaults with ID 11.
The segfault is caused by my print ln:
printf("%s %s\n", "Calling lab_manifes_alignment with package", *package);
But why does this cause a segfault?
Halp?
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
pthread_mutex_t mutex;
FILE *packageList;
void *submitPackage(void * packageReq){
char ** package = packageReq;
strcat(packageReq, " | sh lab_manifest_alignment.sh");
printf("%s %s\n", "Calling lab_manifes_alignment with package", *package);
system(packageReq);
return NULL;
}
int main(){
int numThreads;
pthread_t threads[numThreads];
//Init mutex
if(pthread_mutex_init(&mutex, NULL)){
fprintf(stderr, "Error initializing mutex");
}
int rc;
FILE *packageList = fopen("package_list.txt", "r");
if(packageList == NULL){
fprintf(stderr, "ERROR: cannot open file.\n");
return 1;
}
int i = 0;
char line[128];
while ( fgets ( line, sizeof line, packageList ) != NULL ){
/* read a line spawn as many threads as needeed*/
printf("%s %d, %s\n", "line: ",i, line);
rc = pthread_create(&(threads[i]), NULL, submitPackage, line);
if(rc){
printf("ERROR: return code from pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
i++;
}
numThreads = i;
for(i = 0; i < numThreads; i++){
pthread_join(threads[i], NULL);
}
fclose(packageList);
return 0;
}
pthread_t threads[numThreads]; numThreads is uninitialized here, you should choose a maximum value of threads or allocate it dynamically.
fgets ( line, sizeof line, packageList ) reads 128 bytes into line (the size of the array), but strcat(packageReq, " | sh lab_manifest_alignment.sh"); adds something behind it. This is the reason for your segfault. You should increase the size of the array and decrease the size parameter in fgets.
The next iteration in your main thread overwrites your line array, while the threads working with it. You should use a 2D array or allocate a buffer in each iteration and free it in the thread after working with it. Each thread must get his own buffer, not everyone the same.
char ** package = packageReq; should be char *package = packageReq; and remove the * at the printf.
I think problem in here:
char ** package = packageReq;
Try to change:
char ** package = &packageReq;
I'm new to using the pthread library in C and I have an assignment for my class to write a simple program using them. The basic description of the program is it takes 1 or more input files containing website names and 1 output file name. I then need to create 1 thread per input file to read in the website names and push them onto a queue. Then I need to create a couple of threads to pull those names off of the queue, find their IP Address, and then write that information out to the output file. The command line arguments are expected as follows:
./multi-lookup [one or more input files] [single output file name]
My issue is this. Whenever I run the program with only 1 thread to push information to the output file then everything works properly. When I make it two threads then the program hangs and none of my testing "printf" statements are even printed. My best guess is that deadlock is occurring somehow and that I'm not using my mutexes properly but I can't figure out how to fix it. Please help!
If you need any information that I'm not providing then just let me know. Sorry for the lack of comments in the code.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include "util.h"
#include "queue.h"
#define STRING_SIZE 1025
#define INPUTFS "%1024s"
#define USAGE "<inputFilePath> <outputFilePath>"
#define NUM_RESOLVERS 2
queue q;
pthread_mutex_t locks[2];
int requestors_finished;
void* requestors(void* input_file);
void* resolvers(void* output_file);
int main(int argc, char* argv[])
{
FILE* inputfp = NULL;
FILE* outputfp = NULL;
char errorstr[STRING_SIZE];
pthread_t requestor_threads[argc - 2];
pthread_t resolver_threads[NUM_RESOLVERS];
int return_code;
requestors_finished = 0;
if(queue_init(&q, 10) == QUEUE_FAILURE)
fprintf(stderr, "Error: queue_init failed!\n");
if(argc < 3)
{
fprintf(stderr, "Not enough arguments: %d\n", (argc - 1));
fprintf(stderr, "Usage:\n %s %s\n", argv[0], USAGE);
return 1;
}
pthread_mutex_init(&locks[0], NULL);
pthread_mutex_init(&locks[1], NULL);
int i;
for(i = 0; i < (argc - 2); i++)
{
inputfp = fopen(argv[i+1], "r");
if(!inputfp)
{
sprintf(errorstr, "Error Opening Input File: %s", argv[i]);
perror(errorstr);
break;
}
return_code = pthread_create(&(requestor_threads[i]), NULL, requestors, inputfp);
if(return_code)
{
printf("ERROR: return code from pthread_create() is %d\n", return_code);
exit(1);
}
}
outputfp = fopen(argv[i+1], "w");
if(!outputfp)
{
sprintf(errorstr, "Errord opening Output File: %s", argv[i+1]);
perror(errorstr);
exit(1);
}
for(i = 0; i < NUM_RESOLVERS; i++)
{
return_code = pthread_create(&(resolver_threads[i]), NULL, resolvers, outputfp);
if(return_code)
{
printf("ERROR: return code from pthread_create() is %d\n", return_code);
exit(1);
}
}
for(i = 0; i < (argc - 2); i++)
pthread_join(requestor_threads[i], NULL);
requestors_finished = 1;
for(i = 0; i < NUM_RESOLVERS; i++)
pthread_join(resolver_threads[i], NULL);
pthread_mutex_destroy(&locks[0]);
pthread_mutex_destroy(&locks[1]);
return 0;
}
void* requestors(void* input_file)
{
char* hostname = (char*) malloc(STRING_SIZE);
FILE* input = input_file;
while(fscanf(input, INPUTFS, hostname) > 0)
{
while(queue_is_full(&q))
usleep((rand()%100));
if(!queue_is_full(&q))
{
pthread_mutex_lock(&locks[0]);
if(queue_push(&q, (void*)hostname) == QUEUE_FAILURE)
fprintf(stderr, "Error: queue_push failed on %s\n", hostname);
pthread_mutex_unlock(&locks[0]);
}
hostname = (char*) malloc(STRING_SIZE);
}
printf("%d\n", queue_is_full(&q));
free(hostname);
fclose(input);
pthread_exit(NULL);
}
void* resolvers(void* output_file)
{
char* hostname;
char ipstr[INET6_ADDRSTRLEN];
FILE* output = output_file;
int is_empty = queue_is_empty(&q);
//while(!queue_is_empty(&q) && !requestors_finished)
while((!requestors_finished) || (!is_empty))
{
while(is_empty)
usleep((rand()%100));
pthread_mutex_lock(&locks[0]);
hostname = (char*) queue_pop(&q);
pthread_mutex_unlock(&locks[0]);
if(dnslookup(hostname, ipstr, sizeof(ipstr)) == UTIL_FAILURE)
{
fprintf(stderr, "DNSlookup error: %s\n", hostname);
strncpy(ipstr, "", sizeof(ipstr));
}
pthread_mutex_lock(&locks[1]);
fprintf(output, "%s,%s\n", hostname, ipstr);
pthread_mutex_unlock(&locks[1]);
free(hostname);
is_empty = queue_is_empty(&q);
}
pthread_exit(NULL);
}
Although I'm not familiar with your "queue.h" library, you need to pay attention to the following:
When you check whether your queue is empty you are not acquiring the mutex, meaning that the following scenario might happen:
Some requestors thread checks for emptiness (let's call it thread1) and just before it executes pthread_mutex_lock(&locks[0]); (and after if(!queue_is_full(&q)) ) thread1 gets contex switched
Other requestors threads fill the queue up and when out thread1 finally gets hold of the mutex if will try to insert to the full queue. Now if your queue implementation crashes when one tries to insert more elements into an already full queue thread1 will never unlock the mutex and you'll have a deadlock.
Another scenario:
Some resolver thread runs first requestors_finished is initially 0 so (!requestors_finished) || (!is_empty) is initially true.
But because the queue is still empty is_empty is true.
This thread will reach while(is_empty) usleep((rand()%100)); and sleep forever, because you pthread_join this thread your program will never terminate because this value is never updated in the loop.
The general idea to remember is that when you access some resource that is not atomic and might be accessed by other threads you need to make sure you're the only one performing actions on this resource.
Using a mutex is OK but you should consider that you cannot anticipate when will a context switch occur, so if you want to chech e.g whether the queue is empty you should do this while having the mutex locked and not unlock it until you're finished with it otherwise there's no guarantee that it'll stay empty when the next line executes.
You might also want to consider reading more about the consumer producer problem.
To help you know (and control) when the consumers (resolver) threads should run and when the producer threads produce you should consider using conditional variables.
Some misc. stuff:
pthread_t requestor_threads[argc - 2]; is using VLA and not in a good way - think what will happen if I give no parameters to your program. Either decide on some maximum and define it or create it dynamically after having checked the validity of the input.
IMHO the requestors threads should open the file themselves
There might be some more problems but start by fixing those.
I am learning the concept of multithreading and i encountered a problem using semaphore mutexes.
Here is my code snippet:
void *thread1_funct(void * myfileptr)
{
static int count;
printf("\nThread1 ID:%u\n",(unsigned int) pthread_self());
printf("\nThread1 function, file pointer received:0x%x\n", (FILE*)myfileptr);
for (;;)
{
count++;
sem_wait(&mutex);
fprintf(myfileptr, "%d\n", count);
sem_post(&mutex);
}
return NULL;
}
void *thread2_funct(void *myfileptr)
{
static int count=0;
printf("\nThread2 ID:%u\n",(unsigned int) pthread_self());
printf("\nThread2 function, file pointer received:0x%x\n", (FILE*)myfileptr);
for (;;)
{sem_wait(&mutex);
fscanf(myfileptr, "%d\n", &count);
printf("\n......%d......\n", count);
sem_post(&mutex);
}
return NULL;
}
The two threads i have created. One will write dfata to a file and the other will read the latest data.
Here is my main method:
int main(int argc, char **argv)
{
FILE *fileptr = fopen(*(argv+1), "a+");
sem_init(&mutex, 0x00, 0x01);
if ( (thread1_ret = pthread_create(&thread1, NULL, thread1_funct, (void*)fileptr)) == 0)
printf("\nThread1 created successfully....\n");
else
printf("\nFailed to create Thread1\n");
if ( (thread2_ret = pthread_create(&thread2, NULL, thread2_funct, (void*)fileptr)) == 0)
printf("\nThread2 created successfully....\n");
else
printf("\nFailed to create Thread2\n");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
fclose(fileptr);
sem_destroy(&mutex);
pthread_exit(NULL);
return 0;
}
The expected output is :
........1........
........2........
........3........
and so on...... till the program is interrupted manually.
But my output is all 0s:
........0.......
........0.......
........0.......
........0.......
and so on....
Please help me. Where am i going wrong?
Thread 1 writes to the file, and advances the file pointer - to the end of the file. Thread 2 reads from the file pointer, which is pointing at the end of the file, and so you get nothing.
You could use fseek, or rewind in thread 2 to get your data.