Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tricky Deadlock while programming with Threads in C

I tried to make a file copier using threads and somehow, the programm locks when entering the functions. I searched a lot and I tried many things, but I simply can't find the solution. I would be glad if somebody could help me!

//gcc -o threadcopyfile threadcopyfile.c -lpthread -lrt
#include <stdio.h>
#include <pthread.h> 
#include <unistd.h> 
#include <string.h>
#include <stdlib.h>


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //init mutex
pthread_cond_t condRead = PTHREAD_COND_INITIALIZER; //init cond. variables
pthread_cond_t condWrite = PTHREAD_COND_INITIALIZER; //init cond. variables

int n, x = 1, i = 0, j, condition = 0;
char c;

pthread_t pRead;
pthread_t pWrite;

char ringpuffer[10000];

void *functionRead(void *argv){
    char **args = (char **) argv; //Give args the arguments from argv
    FILE* fp;
    if ((fp=fopen(args[1], "r")) == NULL){ //Open the inputfile, check if failed
        perror("fopen\n"); 
        exit(EXIT_FAILURE);
    }
    n = atoi(args[3]);
    printf("Entered functionRead\n");
    do{
        pthread_mutex_lock(&mutex); //Lock mutex
        while(condition == 1){
            pthread_cond_wait(&condRead, &mutex); //Wait for cond_signal
        }
        i = 0;
        for(i = 0; i<=n; i++){ //Put chars into the ringbuffer
            c = fgetc(fp);
            ringpuffer[i] = c;
            i++;
        }
        x++;
        printf("Hit!");
        condition = 1;
        pthread_mutex_unlock(&mutex); //Unlock mutex
        pthread_cond_signal(&condWrite); //Send signal to CondWrite
    }while ((c=fgetc(fp)) != EOF);

    if ((fclose(fp)) == EOF){ //Close the file
        perror("fclose\n"); 
        exit(EXIT_FAILURE);
    }
    return 0;
}

void *functionWrite(void *argv){
    char **args = (char **) argv;   //Give args the arguments from argv
    FILE* fp;
    if ((fp=fopen(args[2], "w")) == NULL){ //Open the outputfile, check if allowed
        perror("fopen\n"); 
        exit(EXIT_FAILURE);
    }
    n = atoi(args[3]);
    printf("Entered functionWrite\n");
    for (j = 0; j < x; j++){
        pthread_mutex_lock(&mutex); //Lock mutex
        while(condition == 0){
            pthread_cond_wait(&condWrite, &mutex); //Wait for singel from condRead
        }
        fwrite(ringpuffer, 1, n, fp); //Write to file
        printf("Hit too!");
        condition = 0;
        pthread_mutex_unlock(&mutex); //Unlock
        pthread_cond_signal(&condRead); //Send signal again to condRead
    }

    if ((fclose(fp)) == EOF){
        perror("fclose\n"); 
        exit(EXIT_FAILURE);
    }
    return EXIT_SUCCESS;
}

int main(int argc, char **argv)
{
    if (argc != 4){
        printf("Only 3 parameters allowed!\n");
        exit(EXIT_FAILURE);
    }
    printf("File to Copy: %s\nTarget: %s\nHow many chars: %s\n", argv[1], argv[2], argv[3]);

    pthread_create(&pWrite, NULL, &functionWrite, ((void *)argv)); //Create thread, threadid in pWrite, execute functionWrite, and give argv as arguments
    pthread_create(&pRead, NULL, &functionRead, ((void *)argv)); //Create thread, threadid in pRead, execute functionRead and give argv as arguments 

    printf("Threads created, file copy in progress\n");
    pthread_cond_signal(&condRead); //Unblocks the thread

    pthread_join(pRead, NULL);
    pthread_join(pWrite, NULL);
    printf("done.\n");
    return 0;
}
like image 401
Kuro95 Avatar asked Jun 05 '26 16:06

Kuro95


1 Answers

You can't use a single mutex with two condition variables like that. If a thread calls pthread_cond_signal() and relocks the mutex before the second thread wakes up, the second thread will never be able to return from pthread_cond_wait() since it can't lock the mutex.

You also don't seem to be setting condition = 1, as both your functionRead() and functionWrite() have condition = 0 in them.

like image 127
Andrew Henle Avatar answered Jun 10 '26 11:06

Andrew Henle



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!