csegmentation-faultpthreadssemaphorereaderwriterlock

C Segmentation Fault - readers and writers


I'm trying to implement a variation of the readers and writers problem in C, the variation is that writers can either be incrementers or decrementers and they should keep a running count. Below is the code I am trying to implement, I am getting the error "Segmentation Fault (core dumped). I have attempted to debug and received this feedback from gdb - #0 0x0000000000400d84 in main (). I'd appreciate it if someone were able to explain this to me/give me tips on how to fix this fault. Thanks!

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define WAIT 20
#define NEW 0

#define DECREMENT 0
#define INCREMENT 1

#define TIME 5
#define VALUE 1
#define COMMON 0


int readerCount = NEW;
int total = 0;
int v;
sem_t mutex;
sem_t access_data;



int increment_or_decrement() {
    int d;
    return d = rand() % 2;
}

void *writer(void *arg) {
    int version = increment_or_decrement();

    int *iID = (int *) arg;
    int *dID = (int *) arg;

    sleep(rand() % WAIT);

    sem_wait(&access_data);

    if (version == INCREMENT) {
        fprintf(stderr, "Incrementer %d accessed the data\n", *iID);
        total++;
        fprintf(stderr, "Total: %d\n", total);
    }
    else {
        fprintf(stderr, "Decrementer %d accessed the data\n", *dID);
        total--;
        fprintf(stderr, "Total: %d\n", total);
    }

    sleep(TIME);

    sem_post(&access_data);

    pthread_exit(NULL);

}


void *reader(void *arg) {
    int *id = (int *) arg;

    sleep(rand() % WAIT);

    while(1) {
        if (readerCount == NEW) {
            sem_wait(&mutex);

            v = version;
            readerCount++;

            if (readerCount == 1)
                sem_wait(&access_data);

            sem_post(&mutex);

            fprintf(stderr, "Reader %d accessed the data\n", *id);

            sem_wait(&mutex);

            readerCount--;

            if(readerCount == NEW)
                sem_post(&access_data);

            sem_post(&mutex);

            pthread_exit(NULL);
        }
    }

}


int main() {
    int numReaders = rand();
    int numWriters = rand();
    int i;

    sem_init(&mutex, COMMON, VALUE);
    sem_init(&access_data, COMMON, VALUE);

    pthread_t readers[numReaders];
    pthread_t writers[numWriters];

    int readerID[numReaders];
    int writerID[numWriters];

    for (i = 0; i < numReaders; i++)
        readerID[i] = i;

    for (i = 0; i < numWriters; i++)
        writerID[i] = i;

    for (i = 0; i < numReaders; i++) {
        if(pthread_create(&readers[i], NULL, reader, (void *) &readerID[i]) != 0) {
            printf("Child failed\n");
            exit(EXIT_FAILURE);
        }
    }

    for (i = 0; i < numWriters; i++) {
        if (pthread_create(&writers[i], NULL, writer, (void *) &writerID[i]) != 0) {
            printf("Child failed\n");
            exit(EXIT_FAILURE);
        }
    }

    for (i = 0; i < numReaders; i++) {
        if (pthread_join(readers[i], NULL) != 0) {
            printf("Join failed\n");
            exit(EXIT_FAILURE);
        }
    }

    for (i = 0; i < numWriters; i++) {
        if (pthread_join(writers[i], NULL) != 0) {
            printf("Join failed\n");
            exit(EXIT_FAILURE);
        }
    }

    sem_destroy(&access_data);
    sem_destroy(&mutex);
}

Solution

  • You are likely to run out of stack space if rand returns big number as indicated in comments by @WhozCraig

    If you just assign some finite values instead of using rand here:

      int numReaders = rand();
      int numWriters = rand();
    

    I see it running without segmentation fault