munmap() not working when called from function - c

Im writing a library of functions that works with shared memory. The function I am writing to close the shared memory gives me a segfault whenever it gets to the munmap() part, but if i dont use the function and just let the code munmap() and shm_unlink at the end, it works. im very confused as to why. the code is below.
void close_table(table_t *tbl, char* name){
size_t size = sizeof(tbl->table_size);
printf("table_size: %d\n", tbl->table_size);
/* when the first part of if else statement runs its fine */
if(tbl->numP > 1){
printf("first if statement\n");
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
}
/* when second part runs gives seg fault */
else{
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
//close(tbl->shm_fd);
shm_unlink(tbl->name);
}
// Code omission
}
This is the open table function
table_t *open_table(char *name, int record_size, int max_records){
int shm_fd;
int table_size;
void* ptr;
table_t* tbl;
table_t controlBlock;
db_info info;
data_block data;
table_size = max_records * sizeof(controlBlock) * sizeof(info) *
sizeof(data);
if((shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666)) == -1){
exit(EXIT_FAILURE);
}
ftruncate(shm_fd, table_size);
ptr = mmap(NULL, table_size, PROT_WRITE | PROT_READ, MAP_SHARED, shm_fd,
0);
tbl = ptr;
tbl->shm_fd = shm_fd;
tbl->table_size = table_size;
tbl->max_records = max_records;
tbl->record_size = record_size;
if(tbl->numP >= 1){
tbl->numP += 1;
}
else{
tbl->numP = 1;
}
return tbl;
}
these are my structs
typedef struct{
int dbInfoId;
int deleted;
}db_info;
typedef struct{
int shm_fd;
int numP;
int control_id;
char *name;
int table_size;
int record_size;
int max_records;
db_info* dbInfo;
void* db;
}table_t;
typedef struct{
int id;
void* record;
}data_block;
valgrind says its an "invalid read of size 8
enter a command (just the number):
1. Add
2. Delete
3. Process
4. Close
5. # of processes
6. exit
4
table_size: 29360128
==6679== Invalid read of size 8
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679==
==6679==
==6679== Process terminating with default action of signal 11 (SIGSEGV)
==6679== Access not within mapped region at address 0x5654010
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== If you believe this happened as a result of a stack
==6679== overflow in your program's main thread (unlikely but
==6679== possible), you can try to increase the size of the
==6679== main thread stack using the --main-stacksize= flag.
==6679== The main thread stack size used in this run was 8388608.
--6679-- REDIR: 0x50db950 (libc.so.6:free) redirected to 0x4c30cd0 (free)
==6679==
==6679== HEAP SUMMARY:
==6679== in use at exit: 0 bytes in 0 blocks
==6679== total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==6679==
==6679== All heap blocks were freed -- no leaks are possible
==6679==
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==6679==
==6679== 1 errors in context 1 of 1:
==6679== Invalid read of size 8
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679==
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

I figured it the answer. It turns out I was still trying to access variables in the tbl struct after it was unmapped. so to fix this I just created variabbles in the function and saved what I needed from the tbl struct before unmapping.
void close_table(table_t *tbl){
int size = tbl->table_size;
char* name = tbl->name;
int fd = tbl->shm_fd;
printf("table_size: %d\n", tbl->table_size);
if(tbl->numP > 1){
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
close(fd);
}
else if(tbl->numP == 1){
tbl->numP -= 1;
munmap(tbl, size);
printf("unmap works\n"); fflush(stdout);
shm_unlink(name);
close(fd);
}

Related

Invalid read using valgrind

After a compilation with no warnings and errors for my file reorg.c, I am running the program using Valgrind and I am getting the following output. I am trying to understand why I am getting a segmentation fault but I can't really find something wrong with line 35:
Memcheck, a memory error detector
==29338== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29338== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==29338== Command: ./reorg /opt/lsde/dataset-sf100/
==29338==
==29338== Invalid read of size 2
==29338== at 0x109398: main (reorg.c:35)
==29338== Address 0x12cb4008 is not stack'd, malloc'd or (recently) free'd
==29338==
==29338==
==29338== Process terminating with default action of signal 11 (SIGSEGV)
==29338== Access not within mapped region at address 0x12CB4008
==29338== at 0x109398: main (reorg.c:35)
==29338== If you believe this happened as a result of a stack
==29338== overflow in your program's main thread (unlikely but
==29338== possible), you can try to increase the size of the
==29338== main thread stack using the --main-stacksize= flag.
==29338== The main thread stack size used in this run was 8388608.
==29338==
==29338== HEAP SUMMARY:
==29338== in use at exit: 15,280 bytes in 10 blocks
==29338== total heap usage: 10 allocs, 0 frees, 15,280 bytes allocated
==29338==
==29338== LEAK SUMMARY:
==29338== definitely lost: 5,120 bytes in 5 blocks
==29338== indirectly lost: 0 bytes in 0 blocks
==29338== possibly lost: 0 bytes in 0 blocks
==29338== still reachable: 10,160 bytes in 5 blocks
==29338== suppressed: 0 bytes in 0 blocks
==29338== Rerun with --leak-check=full to see details of leaked memory
==29338==
==29338== For lists of detected and suppressed errors, rerun with: -s
==29338== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
This is the code of the reorg.c program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "utils.h"
Person *person_map;
unsigned int *knows_map;
unsigned short *interest_map;
unsigned long person_num = 0;
int main(int argc, char *argv[]) {
unsigned long file_length;
interest_map = (unsigned short *) mmapr(makepath(argv[1], "interest", "bin"), &file_length);
printf("amin1");
knows_map = (unsigned int *) mmapr(makepath(argv[1], "knows", "bin"), &file_length);
printf("amin2");
person_map = (Person *) mmapr(makepath(argv[1], "person", "bin"), &file_length);
printf("amin3");
knows_map = (unsigned int *) mmapr(makepath(argv[1], "knows", "bin"), &file_length);
printf("knows");
person_map = (Person *) mmapr(makepath(argv[1], "person", "bin"), &file_length);
printf("person");
person_num = file_length/sizeof(person_map);
int counter=0;
FILE* fp_knows2 = fopen(makepath(argv[1], "knows2", "bin"), (char*) "w");
FILE* fp_person2 = fopen(makepath(argv[1], "person2", "bin"), (char*) "w");
long knows2_bytesize;
int *knows2_map;
int *person2_map;
long person2_bytesize;
for(long i=0; i<person_num; i++) {
for(long j = 0; j < person_map[i].knows_n; j++) {
int friend = knows_map[person_map[i].knows_first+j]; // person in my knows-list
if (person_map[friend].location == person_map[i].location) {
counter++;
fwrite(&friend, 1,sizeof(int), fp_knows2);
}
}
if(counter > 0){
fwrite(&person_map[i], 1, sizeof(int), fp_person2);
}
counter=0;
}
fclose(fp_knows2);
fclose(fp_person2);
person2_map = (int*) mmapr(makepath(argv[1], "person2","bin"), &person2_bytesize);
knows2_map = (int*) mmapr(makepath(argv[1], "knows2","bin"), &knows2_bytesize);
return 0;
}
And this is the code of the utils.h program that am including in:
#define REPORTING_N 1000000
#define LINEBUFLEN 1024
typedef unsigned long byteoffset;
typedef unsigned int entrycount;
typedef struct {
unsigned long person_id;
unsigned short birthday;
unsigned short location;
unsigned long knows_first;
unsigned short knows_n;
unsigned long interests_first;
unsigned short interest_n;
} Person;
void parse_csv(char* fname, void (*line_handler)(unsigned char nfields, char** fieldvals)) {
long nlines = 0;
FILE* stream = fopen(fname, "r");
if (stream == NULL) {
fprintf(stderr, "Can't read file at %s\n", fname);
exit(-1);
}
char line[LINEBUFLEN];
char* tokens[10];
unsigned int col, idx;
tokens[0] = line;
while (fgets(line, LINEBUFLEN, stream)) {
col = 0;
// parse the csv line into array of strings
for (idx=0; idx<LINEBUFLEN; idx++) {
if (line[idx] == '|' || line[idx] == '\n') {
line[idx] = '\0';
col++;
tokens[col] = &line[idx+1];
} // lookahead to find end of line
if (line[idx+1] == '\0') {
break;
}
}
(*line_handler)(col, tokens);
nlines++;
if (nlines % REPORTING_N == 0) {
printf("%s: read %lu lines\n", fname, nlines);
}
}
fclose(stream);
}
FILE* open_binout(char* filename) {
FILE* outfile;
outfile = fopen(filename, "wb");
if (outfile == NULL) {
fprintf(stderr, "Could not open %s for writing\n", filename);
exit(-1);
}
return outfile;
}
unsigned short birthday_to_short(char* date) {
unsigned short bdaysht;
char dmbuf[3];
dmbuf[2] = '\0';
dmbuf[0] = *(date + 5);
dmbuf[1] = *(date + 6);
bdaysht = atoi(dmbuf) * 100;
dmbuf[0] = *(date + 8);
dmbuf[1] = *(date + 9);
bdaysht += atoi(dmbuf);
return bdaysht;
}
void* mmapr(char* filename, byteoffset *filelen) {
int fd;
struct stat sbuf;
void *mapaddr;
if ((fd = open(filename, O_RDONLY)) == -1) {
fprintf(stderr, "failed to open %s\n", filename);
exit(1);
}
if (stat(filename, &sbuf) == -1) {
fprintf(stderr, "failed to stat %s\n", filename);
exit(1);
}
mapaddr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (mapaddr == MAP_FAILED) {
fprintf(stderr, "failed to mmap %s\n", filename);
exit(1);
}
*filelen = sbuf.st_size;
return mapaddr;
}
char* makepath(char* dir, const char* file, const char* ext) {
char* out = (char*) malloc(1024), *sep = (char*) "";
if (strlen(dir) && dir[strlen(dir)-1] != '/') sep = (char*) "/";
sprintf(out, "%s%s%s.%s", dir, sep, file, ext);
return out;
}

segmentation fault (c language)

While trying to recover jpgs from a raw file in week4 of CS50 course , I got this seg fault error which I can't understand why or how it is caused, all I can tell is that according to valgrind line 110 causes this issue
I am fairly new to c language
int main(int argc, char *argv[])
{
// check if one command arg is passed
if (argc > 2 )
{
printf("Usage: ./recover image\n");
return 1;
}
// try to open file to read from
FILE *file = fopen(argv[1], "r");
if (!file)
{
return 1;
}
BYTE bytes[512];
int x =0 ;
char num[10];
FILE* output =NULL;
while (fread(&bytes, 512, 1, file) == 1)
{
// first step create file name
sprintf(num, "%03i.jpg",x);
// check for start of jpg file
if (bytes[0]==0xff && bytes[1] ==0xd8 && bytes[2]== 0xff && (bytes[3] & 0xf0) == 0xe0 )
{
printf("Found file {%i}", x);
output = fopen(num , "w");
fwrite(&bytes ,512 ,1 ,output);
x++;
}
else
{
fwrite(&bytes , 512 , 1 , output);
}
}
return 0;
}
output of valgrind
==12934== Invalid read of size 4
==12934== at 0x4A1C521: fwrite (iofwrite.c:37)
==12934== by 0x4014CA: main (recover.c:110)
==12934== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==12934==
==12934==
==12934== Process terminating with default action of signal 11 (SIGSEGV)
==12934== Access not within mapped region at address 0x0
==12934== at 0x4A1C521: fwrite (iofwrite.c:37)
==12934== by 0x4014CA: main (recover.c:110)
==12934== If you believe this happened as a result of a stack
==12934== overflow in your program's main thread (unlikely but
==12934== possible), you can try to increase the size of the
==12934== main thread stack using the --main-stacksize= flag.
==12934== The main thread stack size used in this run was 8388608.
==12934==
==12934== HEAP SUMMARY:
==12934== in use at exit: 472 bytes in 1 blocks
==12934== total heap usage: 2 allocs, 1 frees, 4,568 bytes allocated
==12934==
==12934== LEAK SUMMARY:
==12934== definitely lost: 0 bytes in 0 blocks
==12934== indirectly lost: 0 bytes in 0 blocks
==12934== possibly lost: 0 bytes in 0 blocks
==12934== still reachable: 472 bytes in 1 blocks
==12934== suppressed: 0 bytes in 0 blocks
==12934== Rerun with --leak-check=full to see details of leaked memory
==12934==
==12934== For lists of detected and suppressed errors, rerun with: -s
==12934== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
zsh: segmentation fault valgrind ./recover card.raw
take this one
int main(int argc, char *argv[])
{
// check if one command arg is passed
if (argc > 2 )
{
printf("Usage: ./recover image\n");
return 1;
}
// try to open file to read from
FILE *file = fopen(argv[1], "r");
if (!file)
{
return 1;
}
BYTE bytes[512];
int x =0 ;
char num[10];
FILE* output =NULL;
while (fread(bytes, 512, 1, file) == 1)
{
// check for file start
if (bytes[0]==0xff && bytes[1] ==0xd8 && bytes[2]== 0xff && (bytes[3] & 0xf0) == 0xe0 )
{
if (output)
{
fclose(output);
}
// create file name
sprintf(num, "%03i.jpg",x);
printf("Found file {%i}\n", x);
output = fopen(num , "w");
fwrite(&bytes ,512 ,1 ,output);
x++;
}
else if (output)
{
fwrite(bytes , 512 , 1 , output);
}
}
if(output)
{
fclose(output);
}
return 0;
}
notice the use of fclose(output); to close file descriptors, as noted by Marek R
changing
else
{
fwrite(&bytes , 512 , 1 , output);
}
to
else if (output)
{
fwrite(&bytes , 512 , 1 , output);
}
generates the pictures
thanks to Marek R for mentioning the if file is opened comment

POSIX semaphores - cannot determine what causes segmentation fault

I'm working on the sleeping barber problem (using FIFO queue and shared memory), and I have a problem. I try to run this program just to see what is shown, however, I get segmentation fault every time. In the code I check, if semaphores are created successfully, if shared memory is created properly, but the program crashing must come from different place, which I cannot seem to find. I also tried to use Valgrind but what I got is:
Valgrind for the newer version of code:
However, when I try to run the code I still get segfault
==187== Memcheck, a memory error detector
==187== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==187== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==187== Command: ./barber
==187==
Error while executing program, invalid amount of arguments==187==
==187== HEAP SUMMARY:
==187== in use at exit: 0 bytes in 0 blocks
==187== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==187==
==187== All heap blocks were freed -- no leaks are possible
==187==
==187== For lists of detected and suppressed errors, rerun with: -s
==187== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==124== Memcheck, a memory error detector
==124== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==124== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==124== Command: ./barber
==124==
==124== Invalid read of size 1
==124== at 0x1094DD: main (in /mnt/c/users/Czaro/ubuntu/lab6posix/barber)
==124== Address 0x2 is not stack'd, malloc'd or (recently) free'd
==124==
==124==
==124== Process terminating with default action of signal 11 (SIGSEGV)
==124== Access not within mapped region at address 0x2
==124== at 0x1094DD: main (in /mnt/c/users/Czaro/ubuntu/lab6posix/barber)
==124== If you believe this happened as a result of a stack
==124== overflow in your program's main thread (unlikely but
==124== possible), you can try to increase the size of the
==124== main thread stack using the --main-stacksize= flag.
==124== The main thread stack size used in this run was 8388608.
glut==124==
==124== HEAP SUMMARY:
==124== in use at exit: 125 bytes in 4 blocks
==124== total heap usage: 5 allocs, 1 frees, 1,149 bytes allocated
==124==
==124== LEAK SUMMARY:
==124== definitely lost: 0 bytes in 0 blocks
==124== indirectly lost: 0 bytes in 0 blocks
==124== possibly lost: 0 bytes in 0 blocks
==124== still reachable: 125 bytes in 4 blocks
==124== suppressed: 0 bytes in 0 blocks
==124== Reachable blocks (those to which a pointer was found) are not shown.
==124== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==124==
==124== For lists of detected and suppressed errors, rerun with: -s
==124== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault
I'd greatly appreciate every kind of help!
The code for barber (newer version, with changes given by #AndrewHenle looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
int main(char* argv[], int argc)
{
if(argc < 2){
printf("Error while executing program, invalid amount of arguments");
return 0;
}
sem_t *barber;
sem_t *queue;
int seats;
int sharedmem, waitRoomSize;
struct Queue waitroom;
barber = sem_open("Barber", O_CREAT | O_RDWR, 0666, 1);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
queue = sem_open("Queue", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
seats = atoi(argv[1]);
void *space;
queueinit(waitroom, seats);
sharedmem = shm_open("Queue", O_RDWR, 0666);
if(sharedmem==-1){
printf("Error while getting shared memory");
exit(1);
}
waitRoomSize = ftruncate(sharedmem, sizeof(waitroom));
if((waitRoomSize ==-1)){
printf("Error while getting size");
exit(1);
}
space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
if((space == MAP_FAILED)){
printf("B³¹d podczas mapowania pamiêci");
exit(1);
}
while(1)
{
printf("Starting work...");
sem_wait(queue);
sem_post(queue);
if(isEmpty(waitroom)) {
sem_wait(barber);
printf("Falling asleep \n");
sem_post(barber);
printf("Waking up \n");
}
sem_wait(queue);
sem_post(queue);
int id = get(waitroom);
printf("Customer: %d, please sit on the chair", id);
printf("I start making haircut: %d", id);
sleep(2);
printf("Finished making haircut for: %d", id);
}
sem_close(barber);
sem_unlink("Barber");
sem_close(queue);
sem_unlink("Queue");
}
Previous version:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
int main(char* argv, int argc)
{
sem_t *barber;
sem_t *queue;
int seats;
int sharedmem, waitRoomSize;
struct Queue waitroom;
barber = sem_open("Barber", O_CREAT | O_RDWR, 0666, 1);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
queue = sem_open("Queue", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
seats = atoi(argv[1]);
void *space;
queueinit(waitroom, seats);
if((sharedmem = shm_open("Queue", O_RDWR, 0666)==-1)){
printf("Error while getting shared memory");
exit(1);
}
if((waitRoomSize = ftruncate(sharedmem, sizeof(waitroom))==-1)){
printf("Error while getting size");
exit(1);
}
if((space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0) == MAP_FAILED)){
printf("Błąd podczas mapowania pamięci");
exit(1);
}
while(1)
{
printf("Starting work...");
sem_wait(queue);
sem_post(queue);
if(isEmpty(waitroom)) {
sem_wait(barber);
printf("Falling asleep \n");
sem_post(barber);
printf("Waking up \n");
}
sem_wait(queue);
sem_post(queue);
int id = get(waitroom);
printf("Customer: %d, please sit on the chair", id);
printf("I start making haircut: %d", id);
sleep(2);
printf("Finished making haircut for: %d", id);
}
sem_close(barber);
sem_unlink("Barber");
sem_close(queue);
sem_unlink("Queue");
}
The FIFO queue is implemented like this:
#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED
#include <stdlib.h>
#include <unistd.h>
struct Queue{
int* elems;
int qsize;
int head;
int tail;
int capacity;
};
void queueinit(struct Queue q, int capacity)
{
q.elems = malloc(capacity*(sizeof(int)));
q.capacity = capacity;
q.head = 0;
q.qsize = 0;
q.tail = capacity-1;
}
int isFull(struct Queue q)
{
return (q.qsize == q.capacity);
}
int isEmpty(struct Queue q)
{
return (q.qsize == 0);
}
void push(struct Queue q, int val)
{
if(isFull(q)){
printf("Kolejka pe³na");
return;
}
q.tail = (q.tail +1) % q.capacity;
q.elems[q.tail] = val;
q.qsize = q.qsize +1;
printf("%d zajmuje miejsce w kolejce", val);
}
int get(struct Queue q)
{
if(isEmpty(q))
{
printf("kolejka pusta");
return -1;
}
int val = q.elems[q.head];
q.head = (q.head +1) % q.capacity;
q.qsize = q.qsize -1;
printf("%d opuszcza zak³ad", val);
}
#endif // FUNCTIONS_H_INCLUDED

Segmentation fault (core dump) First reader-writer problem

#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)
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.

How to free this strdup?

I am using strdup to duplicated the value inside command. I also free it at the end of my loop to make sure I don't have anything leaking but valgrind seems to disagree with me and says that what is allocated with this strdup is leaking. Any ideas?
Here is my code:
int main(void)
{
init_ui();
hist_init(100);
char *command;
while (true) {
signal(SIGINT, SIG_IGN);
command = read_command();
if (command == NULL) {
break;
}
char *copy = strdup(command);
char *args[4096];
int tokens = 0;
char *next_tok = command;
char *curr_tok;
while((curr_tok = next_token(&next_tok, " \t\n\r")) != NULL) {
if(strncmp(curr_tok, "#", 1) == 0){
break;
}
args[tokens++] = curr_tok;
}
args[tokens] = NULL;
if(args[0] == NULL) {
continue;
}
hist_add(copy);
int builtin_status = handle_builtins(tokens, args);
if(builtin_status == 0) {
continue;
}
pid_t child = fork();
if(child == -1){
perror("fork");
}
else if(child == 0){
int ret = execvp(args[0], args);
if(ret == -1) {
perror("execvp");
}
close(fileno(stdin));
close(fileno(stdout));
close(fileno(stderr));
exit(EXIT_FAILURE);
}
else {
int status;
waitpid(child, &status, 0);
set_last_status(status);
}
hist_destroy();
free(copy);
}
return 0;
}
Here is what valgrind gives me, I really am trying to understand what is wrong because it seems like what is defined with this strdup is freed:
HEAP SUMMARY:
==359074== in use at exit: 18 bytes in 2 blocks
==359074== total heap usage: 72 allocs, 70 frees, 20,000 bytes allocated
==359074==
==359074== 18 bytes in 2 blocks are definitely lost in loss record 1 of 1
==359074== at 0x483977F: malloc (vg_replace_malloc.c:307)
==359074== by 0x4A7D23E: strdup (in /usr/lib/libc-2.31.so)
==359074== by 0x10A703: main (shell.c:85)
==359074==
==359074== LEAK SUMMARY:
==359074== definitely lost: 18 bytes in 2 blocks
==359074== indirectly lost: 0 bytes in 0 blocks
==359074== possibly lost: 0 bytes in 0 blocks
==359074== still reachable: 0 bytes in 0 blocks
==359074== suppressed: 0 bytes in 0 blocks
strdup() uses malloc() to allocate memory, so in order to reuse strdup(), copy must be freed.
As UnholySheep commented above, continues causing to ignore the free() statement. One solution to fix this issue is to put an extra free() statement before each continue.

Resources