0
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>

int sleepval = 10, read_num = 0;
int readcnt = 0, writecnt = 0;
pthread_mutex_t mutex;
sem_t rw_mutex;

int randomGenerator(int high, int low){
    srand(time(0));
    return((rand() % (high - low + 1)) + 100);
}

void *reader(void *readno){
    pthread_mutex_lock(&mutex);
    read_num++;
    /* Block the writer if this is the first reader */
    if(read_num == 1){
        sem_wait(&rw_mutex);
    }
    pthread_mutex_unlock(&mutex);
    /* Read sleepval value and print */
    printf("Reader %03d reads %d\n", *((int *)readno), sleepval);
    readcnt++;
    sleep(sleepval / 1000);
    pthread_mutex_lock(&mutex);
    read_num--;
    /*Wake up writer if this is the last reader */
    if(read_num == 0){
        sem_post(&rw_mutex);
    }
    pthread_mutex_unlock(&mutex);
    int num = randomGenerator(500, 100);
    sleep(num / 1000);
}

void *writer(void *writeno){
    int num = randomGenerator(1000, 100);
    sleep(num / 1000);
    num = randomGenerator(50, 10);
    sem_wait(&rw_mutex);
    sleepval = num;
    printf("Writer %02d writes &d\n", *((int*)writeno), sleepval);
    writecnt++;
    sleep(sleepval / 1000);
    sem_post(&rw_mutex);
}

int main(int argc, char *argv[]){
    int r = atoi(argv[1]);
    int w = atoi(argv[2]);
    int second = 0;
    int i, id[100];
    if(r < 1 || r > 100 || w < 1 || w > 10){
        fprintf(stderr, "Usage: readwrite [read](1 - 100) [write](1 - 10)\n");
        exit(-1);
    }
    
    pthread_t read[100], write[10];
    pthread_mutex_init(&mutex, NULL);
    sem_init(&rw_mutex, 0 , 1);

    /* Create threads for readers */
    for(i = 0; i < r; i++){
        id[i] = i;
        pthread_create(&read[i], NULL, (void *)reader, (void *)&id[i]);
    }
    /* Create threads for writers */
    for(i = 0; i < w; i++){
        id[i] = i;
        pthread_create(&write[i], NULL, (void *)writer, (void *)&id[i]);
    }

    sleep(30); //wait for 30 seconds

    /* Signal threads to finish */
    for (i = 0; i < r; i++){
        pthread_join(read[i], NULL);
    }
    for (i = 0; i < w; i++){
        pthread_join(write[i], NULL);
    }

    /* Display number of occurred reads and writes */
    printf("\n==============================\n");
    printf("Number of reads  :\t%03d\n", readcnt);
    printf("Number of writes :\t%03d\n", writecnt);

    pthread_mutex_destroy(&mutex);
    sem_destroy(&rw_mutex);

    return 0;
}

This assignment is about solving the first reader-writer problem. I could compile it in linux using gcc -lpthread -lrt. But when I try to run it using the given format readwrtie 100 10 I got the segmentation fault (core dump) and I don't know why. I tried running with valgrind a.out to see the problem and I couldnt understand. Please help me.

Memcheck, a memory error detector

==19787== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.

==19787== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info

==19787== Command: a.out

==19787==

==19787== Invalid read of size 1

==19787== at 0x57E7AC: ____strtol_l_internal (in /lib/libc-2.12.so)

==19787== by 0x57E50F: strtol (in /lib/libc-2.12.so)

==19787== by 0x57AEB0: atoi (in /lib/libc-2.12.so)

==19787== by 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)

==19787== Address 0x0 is not stack'd, malloc'd or (recently) free'd

==19787==

==19787==

==19787== Process terminating with default action of signal 11 (SIGSEGV)

==19787== Access not within mapped region at address 0x0

==19787== at 0x57E7AC: ____strtol_l_internal (in /lib/libc-2.12.so)

==19787== by 0x57E50F: strtol (in /lib/libc-2.12.so)

==19787== by 0x57AEB0: atoi (in /lib/libc-2.12.so)

==19787== by 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)

==19787== If you believe this happened as a result of a stack

==19787== overflow in your program's main thread (unlikely but

==19787== possible), you can try to increase the size of the

==19787== main thread stack using the --main-stacksize= flag.

==19787== The main thread stack size used in this run was 10485760.

==19787==

==19787== HEAP SUMMARY:

==19787== in use at exit: 0 bytes in 0 blocks

==19787== total heap usage: 0 allocs, 0 frees, 0 bytes allocated

==19787==

==19787== All heap blocks were freed -- no leaks are possible

==19787==

==19787== For counts of detected and suppressed errors, rerun with: -v

==19787== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 8)

Segmentation fault (core dumped)

Lunah
  • 1
  • "using the given format readwrtie 100 10". What does that mean exactly? Please show the exact command you are running. The stack trace suggests some program args may be missing. Also, add code in to check `argc` before accessing any of the `argv` entries. – kaylum Nov 18 '20 at 06:35
  • 2
    Also, a debugger would be more helpful than valgrind in this case. The program will break into the debugger when the seg fault happens and you can then examine the variables, in particular `argv` and `argc`. – kaylum Nov 18 '20 at 06:37

1 Answers1

0

In your writer function, change

printf("Writer %02d writes &d\n", *((int*)writeno), sleepval);
---------------------------^

to

printf("Writer %02d writes %d\n", *((int*)writeno), sleepval);
---------------------------^

In your main function, change

pthread_create(&read[i], NULL, (void *)reader, (void *)&id[i]);
pthread_create(&write[i], NULL, (void *)writer, (void *)&id[i]);

to

pthread_create(&read[i], NULL, reader, &id[i]);
pthread_create(&write[i], NULL, writer, &id[i]);

Add a return statement to the reader and writer function. Remove the unused variable second in the main function.

Try again.

Erdal Küçük
  • 4,810
  • 1
  • 6
  • 11