0

I am trying to write a parallel simulator, that uses threads. But I cannot find what causes segmentation fault and why threads seem to get stuck on a barrier sometimes.

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

int num_threads = 5;

//Thread arguemnt struct
struct ThreadArguments {
        unsigned int id;
        pthread_barrier_t* barrier;
        char* array;  
        char* copy_array; 
};

void simulate(struct ThreadArguments* args);

void initializeThreads( struct ThreadArguments* data,  char* letters);


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

        int i;
        char* letters = malloc((num_threads + 1) *sizeof(char)); //plus 1 for /0
        struct ThreadArguments *data = malloc(num_threads * sizeof(struct ThreadArguments));
        initializeThreads(data, letters);

        pthread_t *thread = malloc(num_threads*sizeof(pthread_t));

        // Launching Threads
        for (i=0; i<num_threads; i++) {
                printf("Create threads %d \n", i);
                fflush(stdout);
                pthread_create(&thread[i], NULL,(void *) &simulate,(void *) &data[i]);
        }

        // Waiting for Threads to Finish
        for (i=0; i<num_threads; i++) {
                pthread_join(thread[i], NULL);
        }
        return 0;
}

void initializeThreads( struct ThreadArguments* data,  char* letters)
{
        int i;
        pthread_barrier_t barrier;  //create a barrier
        pthread_barrier_init (&barrier, NULL, num_threads);

        char *copy_letters = malloc((num_threads + 1) * sizeof(char));
        if(copy_letters == NULL)      //Checking malloc
        {
                perror("Error mallocing");
                free(copy_letters);
                return;
        }

        for (i = 0; i < num_threads; i++)
        {
                data[i].barrier = &barrier;
                data[i].array = letters;
                data[i].copy_array = copy_letters;
                data[i].id = i;
        }

}

void simulate(struct ThreadArguments* args)
{

        struct ThreadArguments* my_args= (struct ThreadArguments*)args;
        printf("thread %d started", my_args->id);
        fflush(stdout);

        if(my_args->id == 0)  //print the initial state of the board
        {
                printf("0th thread prints out results");
        }

        ///Main loop. Each iteration is one round of simulation

        my_args->copy_array[my_args->id] = my_args->array[my_args->id];
        //DO SOME WORK HERE

        //barrier
        pthread_barrier_wait (my_args->barrier);
}

I tried commenting out parts and tracing it with valgrind ( and helgrind tool)but still was not able understand what causes error. The code could be tested with ./simulator test.txt 0 0 1 where test.txt is the following

What is wrong with the way I implement barriers? and what causes SEGFAULT? EDIT: Updated with a shorter version of the code. This code just wants to create num_thread number of threads and each of them would copy one elements from array to another.

dragosht
  • 3,237
  • 2
  • 23
  • 32
Alex Smirnov
  • 21
  • 1
  • 9
  • 3
    There is way too much code here. – mathematician1975 Dec 21 '15 at 07:53
  • I tried posting less and people said its hard to see if the code could not be compiled – Alex Smirnov Dec 21 '15 at 08:02
  • But you could try a *little* harder to make a compact working example.Your `evolve` function contains about 70 lines of commented out code for example. You say you are getting a segfault. Where in the code is the segfault occurring? – talonmies Dec 21 '15 at 08:06
  • Why are you passing the `filename` as `char**`..simply pass the `filename` and catch it with `char*` – Mayukh Sarkar Dec 21 '15 at 08:06
  • 1
    Please provide a shorter version of code or mention where are you getting the segmentation fault – Mayukh Sarkar Dec 21 '15 at 08:09
  • @Mayukh Sarka I have shortened the code to only show most important parts. It still produces segmentation fault in pthread_join or gets stuck waiting at a barrier. – Alex Smirnov Dec 21 '15 at 08:48
  • Change `pthread_create(&thread[i], NULL,(void *) &simulate,(void *) &data[i]);` to `pthread_create(&thread[i], NULL, simulate, &data[i]);`. But you may have other problems. – P.P Dec 21 '15 at 08:55
  • @AlexSmirnov Your `data` is already a pointer and in `pthread_create` you are passing address of the pointer and hence I think you need to catch it with `struct ThreadArguments** args` in `simulate` function...or else just simply pass `data[i]` instead of `&data[i]` – Mayukh Sarkar Dec 21 '15 at 09:06
  • I though about it, but it gives an error `simulation.c:43:25: error: cannot convert to a pointer type pthread_create(&thread[i], NULL,(void *) &simulate,(void *) data[i]);` – Alex Smirnov Dec 21 '15 at 09:09

1 Answers1

1
void initializeThreads( struct ThreadArguments* data,  char* letters)
{
    int i;
    pthread_barrier_t barrier;  //create a barrier

You created barrier on the stack in initializeThreads, so when this function returns, it ceases to exist. So all the threads you create are accessing an object that no longer exists through a stale pointer.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278