Skip to content
Advertisement

Segmentation Fault on pthread_create

I am having an issue with the following C code. The code itself is supposed to create 5 threads that simulate the Dining Philosophers problem in which threads are accessing shared data. The code follows:

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

//creation of the mutex lock, condition variables, and state
pthread_mutex_t mutex;
pthread_cond_t cond_var[5];
enum{THINKING, HUNGRY, EATING}state[5];

//test if possible to get forks
void test(int pNumber){

    //start eating if the adjacent philosophers aren't eating
    if((state[(pNumber + 1) % 5] != EATING) && (state[(pNumber + 4) % 5] != EATING)){
        state[pNumber] = EATING;

        //signal self if test() called by another thread
        pthread_cond_signal(&cond_var[pNumber]);
    }
}

//used to make the philosopher's forks unavailable
void pickup_forks(int pNumber){

    //get lock
    pthread_mutex_lock(&mutex);

    //set state to hungry
    state[pNumber] = HUNGRY;
    printf("Philosopher %d is HUNGRYn", pNumber);

    //attempt to begin eating. if unable to, will wait
    test(pNumber);
    while(state[pNumber] != EATING){
        pthread_cond_wait(&cond_var[pNumber], &mutex);
        //switched the order of the arguments
    }

    //release lock
    pthread_mutex_unlock(&mutex);
}

//allow neighbors to use philosopher's forks
void release_forks(int pNumber){

    //get lock
    pthread_mutex_lock(&mutex);

    //set own state to thinking
    state[pNumber] = THINKING;

    //tell adjacent philosophers to try to eat
    test(((pNumber + 1) % 5)); 
    test(((pNumber + 4) % 5));

    //release lock
    pthread_mutex_unlock(&mutex);
}

//used by the thread to run the philosophers
void *runPhilosopher(void *x){

    //which philosopher it is
    int pNumber = *((int*) x);

    //initially thinking
    state[pNumber] = THINKING;
    printf("Philosopher %d is THINKINGn", pNumber);

    //"think" for a random amount of time between 1-3 seconds
    int sleepTime = rand() % 3 + 1;
    sleep(sleepTime);

    //each philosopher eats a total of 5 times
    int i = 0;
    for(i = 0; i < 5; i++){

        //get the forks and begin eating
        pickup_forks(pNumber);

        //eating time
        sleep(2);

        //put down forks and resume thinking
        release_forks(pNumber);
        sleepTime = rand() % 3 + 1;
        sleep(sleepTime);
    }

    printf("Philosopher %d has finished eatingn", pNumber);
}

int main(int argc, char *argv[])
{

    pthread_mutex_init(&mutex, NULL);

    int i = 0;
    for(i = 0; i < 5; i++){
        pthread_cond_init(&cond_var[i], NULL);
    }


    pthread_t tid[5];    //thread id
    pthread_attr_t attr;     //set of thread attributes

    pthread_create(&tid[0], NULL, runPhilosopher, (void *) 0);
    pthread_create(&tid[1], NULL, runPhilosopher, (void *) 1);
    pthread_create(&tid[2], NULL, runPhilosopher, (void *) 2);
    pthread_create(&tid[3], NULL, runPhilosopher, (void *) 3);
    pthread_create(&tid[4], NULL, runPhilosopher, (void *) 4);

    //wait for threads to finish
    for(i = 0; i < 5; i++){
        pthread_join(tid[i], NULL);
    }

    return 0;
}

I am on a Linux virtual machine, using gedit. The program compiles fine, but upon attempting to run it, I am getting a “Segmentation Fault” error, which is coming from the attempted thread creations, according to gdb. None of the related questions here that I found applied to my program.

Things I have tried:

  • Commenting out the vast majority of the code and attempting to create a single thread that simply runs runPhilosopher, which had been stripped to just a single printf statement. This resulted in the code seemingly not creating the thread, as there was no output.
  • Replacing NULL in the thread creations with &attr. This changed the error to Aborted, but did nothing else.
  • Using a single thread id for all of them, as I have in a previous program. This made no difference.
  • A few other odds and ends that I can’t remember

Does anybody see a simple solution that I’ve simply overlooked, or is there a serious flaw in my program? I can’t understand what the issue could be, but I fully admit that I’m hardly well-versed in C. Any help would be greatly appreciated!

Advertisement

Answer

Your problem is here:

int pNumber = *((int*) x);

You cast an integer to a pointer when you call pthread_create(), but then you cast it to a pointer in the thread function and proceed to dereference it.

Instead, try

    int pNumber = (int) x;

Note that this may cause a compiler warning of sizeof(int) != sizeof(void*). You may want to cast to uintptr_t first.

Alternatively, you could store the int in a local variable and pass the address of this to pthread_create. Just be sure that all threads have stopped before the containing function returns.

Or, you could malloc a structure with this int as a member, and pass a pointer to it.

Advertisement