Double freedom or corruption (! Prev) pthread

I am having trouble implementing a multi-threaded program. The program seems to work fine for one thread (when I set THREADS to 1), but for NTHREADS> 1 I get the following error: Segmentation fault (core dumped)

or

double free or corruption (!prev)

or

free(): invalid size: 0xb6b00a10 *** 0Aborted (core dumped)

as you can see, the error varies a lot and I am confused.

The program I am running is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#define NTHREADS 5
typedef struct data_t
{
    int num;
    FILE *fp;
    pthread_mutex_t mutex;
    int thread_id;
}data_t;

void writefp(int num1, FILE *fp){
    if(fp!=NULL){
        int i;
        int nume = 1;
        int long_var=log10(nume);
        for(i=long_var;i>=0;i--){
            nume=(num1 / (int) round(pow(10, i)) % 10);
            char d=nume+'0';
            fwrite(&d, 1, 1, fp);
            printf("%c", d);
        }
    }
    fclose(fp);
}

void *thread_writefp(void* args)
{
    data_t *data = (data_t *)args;
    printf(" Thread id %d\n", data->thread_id);

    pthread_mutex_lock(&(data->mutex));
    writefp(data->num, data->fp);
    pthread_mutex_unlock(&(data->mutex));
    pthread_exit(NULL);
}
int randomf(){
    int num,i;
    for(i = 0; i<2; i++) {
        num = rand()%100000+1;
    }
    return num;
}

int prime(int num1){
    int is_prime=1;
    int i = 2;
    printf("Number: ");
    while( i<=num1/2 && is_prime==1 ) {
        printf("%i ", i);
        if(i%30==0){
            printf("\n");
        }
        if( num1 % i == 0 ) {
                is_prime = 0;
        }
        i++;
    }
    printf("\n");
    if(is_prime){
            printf("%i is number prime\n", num1);
    }else{
             printf("NO is prime %i\n",num1);
    }
    return 0;
}


int main(void){
    int i;
    //int num1=randomf();
    srand(time(NULL));
    FILE *fp = fopen("fich.txt", "w+b");

    data_t data;
    pthread_t consumers_thread[NTHREADS];
    data.mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
    data.fp = fp;

    //writefp( num1, fp);
    for(i = 0; i < NTHREADS; i++)
    {
        data.num = randomf();
        data.thread_id = i;
        printf("Number prime is %i\n", prime(data.num));
        if(pthread_create(&consumers_thread[i], NULL, 
                    thread_writefp, (void*) &data) != 0)
        {
            fprintf(stderr, "%s\n", "Error creating thread!");
            return EXIT_FAILURE;
        }
    }
    // wait for all consumers thread to finish
    for(i = 0; i < NTHREADS; ++i)
    {
        pthread_join(consumers_thread[i], NULL);
    }
    return EXIT_SUCCESS;
}

      

I will compile the program like this:

$gcc -pthread -Wall -o consummer consummer.c -lm 

      

Here is an example of a tree error that I got when I ran it with a gdb

tree in a row without changing anything in the code:

1

Thread 2 "consummer" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7cc1b40 (LWP 18122)]
tcache_thread_freeres () at malloc.c:3003
3003    malloc.c: No such file or directory.
(gdb) bt
#0  tcache_thread_freeres () at malloc.c:3003
#1  0xb7e258c2 in __libc_thread_freeres () at thread-freeres.c:29
#2  0xb7ea03ad in start_thread (arg=0xb7cc1b40) at pthread_create.c:478
#3  0xb7dbb0a6 in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:108
(gdb) 

      

2

Thread 3 "consummer" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb72ffb40 (LWP 18131)]
0xb7d2af2b in __GI__IO_fwrite (buf=0xb72ff30f, size=1, count=1, fp=0x404160) at iofwrite.c:37
37  iofwrite.c: No such file or directory.
(gdb) run

      

3

Thread 3 "consummer" received signal SIGABRT, Aborted.
[Switching to Thread 0xb74c0b40 (LWP 18143)]
0xb7fd7cf9 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fd7cf9 in __kernel_vsyscall ()
#1  0xb7cf17e2 in __libc_signal_restore_set (set=0xb74bfe9c) at ../sysdeps/unix/sysv/linux/nptl-signals.h:80
#2  __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:48
#3  0xb7cf2f51 in __GI_abort () at abort.c:90
#4  0xb7d340cc in __libc_message (action=(do_abort | do_backtrace), fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:181
#5  0xb7d3af5d in malloc_printerr (action=<optimized out>, str=0xb7e418d8 "double free or corruption (!prev)", ptr=<optimized out>, 
ar_ptr=0xb7e967a0 <main_arena>) at malloc.c:5425
#6  0xb7d3bb3b in _int_free (av=0xb7e967a0 <main_arena>, p=<optimized out>, have_lock=have_lock@entry=0) at malloc.c:4174
#7  0xb7d3fcb0 in __GI___libc_free (mem=0x404160) at malloc.c:3144
#8  0xb7e2587d in tcache_thread_freeres () at malloc.c:3004
#9  0xb7e258c2 in __libc_thread_freeres () at thread-freeres.c:29
#10 0xb7ea03ad in start_thread (arg=0xb74c0b40) at pthread_create.c:478
#11 0xb7dbb0a6 in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:108
(gdb) 

      

I would like / welcome your help to know what I did wrong, please. Thank you in advance.

+1


source to share


1 answer


Per this answer ( but see section Edit 2 )), multiple threads cannot safely access the same FILE *fp

. As @IlyaBursov pointed out, you only have one data_t data

common to all threads - and therefore only one FILE *

data.fp

.

Thanks for your comment noting that you moved fopen

to a stream function. This way, each thread independently opens and closes the file, so there is no cross-thread FILE *

.

This seems to be implementation dependent - I have not been able to reproduce the problem on Cygwin x64 with gcc 6.4.0. I suspect that the effect of the mutex can also change depending on the implementation. It can also depend on compiler options - see this example .



Edit . As @MichaelDorgan pointed out, calling fclose

in FILE *

that uses other threads is also bad.

Edit 2 As @JohnBollinger points out, individual threading operations are currently thread safe . This suggests that there is a problem with fclose

before another thread tries to access the file. However I am wondering if it is possible that the OP's stdio implementation is incorrect. I think compliantfwrite

will just return an error when accessing the closed file, not a crash. See further comments below.

+1


source







All Articles