Home > Mobile >  segFault on return from pthread_join
segFault on return from pthread_join

Time:03-29

I am implementing a stack pool to do some basic arithmetic in a specific number of threads.

here is the code:

int add(int a, int b) {return a b;}
int sub(int a, int b) {return a-b;}
int mul(int a, int b) {return a*b;}
sem_t sem_ops;
void* compute(void* arg){
    Args *args = arg;
    Operation* op = args->operation;
    printOP(*op);
    int * value = malloc ( sizeof ( int ) ) ;
    * value = op->op(op->a, op->b);
    args->is_complete = true;
    sem_post(&sem_ops);
    return value;
}
void push(Operation op , Queue* q){
    q->operations[  (q->last)] = op;
}
Operation *pop(Queue *q){
    q->first  ;
    return &q->operations[q->first];
}
int size(Queue *q){
    return q->last - q->first;
}
               
bool read_operations(char* filename, Queue* ops){
    printf("reading from file %s\n",filename);
    FILE *fp = fopen(filename, "r");
    if(fp == NULL ) 
    {
        printf("couldnt open");
        return false;
    }
    int id,a,b;
    while(!feof(fp)){
        fscanf(fp,"%d %d %d\n",&id,&a,&b);
        Operation op;
        op.a = a;
        op.b = b;
        switch (id){
            case 0:
                op.op = add;
                break;
            case 1:
                op.op = sub;
                break;
            case 2:
            default:
                op.op =mul;
                break;
        }
        push(op,ops);
    }
    return true;
}
ArrayList* execute_thread_pool(char* filename, int poolSize){
    sem_init(&sem_ops,0,poolSize);
    //init return value
    ArrayList* retval =malloc(sizeof(ArrayList));
    int res [ TOTAL_OP_COUNT];
    retval->results = res;
    retval->count = 0;
    // populate Q
    Queue q;
    Operation ops[TOTAL_OP_COUNT];
    q.first = 0;
    q.last = 0;
    q.max = TOTAL_OP_COUNT;
    q.operations = ops;
    read_operations(filename,&q);
    // thread tids
    pthread_t threads[TOTAL_OP_COUNT];
    //args for each thread
    Args args[TOTAL_OP_COUNT];
    int* result= NULL;
    for(int i =0; i<poolSize;   i){
        sem_wait(&sem_ops);
        args[i].operation = pop(&q);
        args[i].is_complete=false;
        pthread_create(&threads[i],NULL, compute,&args[i]);
    }
    for(int i =0; i<poolSize;   i){
        if(args[i].is_complete){
            pthread_join(threads[i],(void**) result);
            res[i] = *result; // line 88
        }else --i;
    }
    return retval;
}

and the structs typedefs:

typedef struct _Operation{
    int(*op) (int, int);
    int a;
    int b;
} Operation;
typedef struct _Args{
    Operation* operation;
    bool is_complete;
}Args;
typedef struct _Queue{
    Operation* operations;
    int last;
    int first;
    int max;
}Queue;

I tried using malloc at a few different places, but can't run away from segfault. this is the content of the main function:

    ArrayList *al =malloc(sizeof(ArrayList)) ;
    al = execute_thread_pool("bob.txt", 4);

in gdb the bt is as follow:

#0  0x0000555555555762 in execute_thread_pool (filename=0x555555556004 "bob.txt", poolSize=4) at pool.c:88
#1  0x00005555555552db in main (argc=1, argv=0x7fffffffda68) at main.c:5

I've been on this for a few hours, tried multiple ways, tried without semaphores and using not so fun loops and yet the same result. can anyone help me spot the issue?

CodePudding user response:

You misunderstand the pthread_join call and how emulating pass-by-reference work in works.

You are supposed to pass a pointer to an int * variable, using the pointer-to operator &:

pthread_join(threads[i], &result);

You should also remember to free the pointer result, or you will have a memory leak.

  • Related