Reputation: 13
I'm using threads and mutex with it. But for some reason, i can't figure out why, i get some segmentation faults. Can't use gdb because i cannot get that error =/
Also i tried to make some prints between lines but cannot see any relevant information...
Can someone tell my why is this happening ?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
// Not order for easy random implementation
#define CITY_B 1
#define CITY_A 2
#define CITY_C 3
#define CITY_D 4
#define TRAIN_NUMBER 3
pthread_mutex_t lineAB;
pthread_mutex_t lineBC;
pthread_mutex_t lineBD;
typedef struct {
int num;
int from;
int to;
}Train;
int generateRandom(int min, int max, int seed) {
srand(time(NULL)+seed);
return ((rand()%max)+min);
}
char * getCurrentTime() {
char * timeString = (char *) malloc(sizeof(char) * 20);
time_t now = time(NULL);
strftime(timeString, 20, "%H:%M:%S", localtime(&now));
return timeString;
}
char * hora() {
return getCurrentTime();
}
pthread_mutex_t * nextLine(int from, int to) {
switch(from) {
case CITY_A: {
return &lineAB;
}
case CITY_B: {
switch(to) {
case CITY_A: {
return &lineAB;
}
case CITY_C: {
return &lineBC;
}
case CITY_D: {
return &lineBD;
}
}
break;
}
case CITY_C: {
return &lineBC;
}
case CITY_D: {
return &lineBD;
}
}
}
char * getCityName(int num) {
switch(num) {
case CITY_A: {
return "City A";
}
case CITY_B: {
return "City B";
}
case CITY_C: {
return "City C";
}
case CITY_D: {
return "City D";
}
}
}
char * getLineName(int from, int to) {
switch(from) {
case CITY_A: {
return "cityA-cityB";
break;
}
case CITY_B: {
switch(to) {
case CITY_A: {
return "cityA-cityB";
break;
}
case CITY_C: {
return "cityB-cityC";
break;
}
case CITY_D: {
return "cityB-cityD";
break;
}
}
break;
}
case CITY_C: {
return "cityB-cityC";
break;
}
case CITY_D: {
return "cityB-cityD";
break;
}
}
}
void * threadFunc(void *arg){
Train * train = (Train*)arg;
/*int trainNum = info[0];
int from = info[1];
int to = info[2];*/
char * partida = hora();
char * chegada;
printf("Train %d, From: %s, To: %s\n", train->num, getCityName(train->from), getCityName(train->to));
//printf("A\n");
pthread_mutex_t * myMutex = nextLine(train->from, CITY_B);
pthread_mutex_lock(myMutex);
//printf("B\n");
printf("Train: %d\tLine: %s\tFrom: %s\tTo: %s\n", train->num,
getLineName(train->from, CITY_B), getCityName(train->from), getCityName(train->to));
// Each line takes x sec to finish
//printf("C\n");
sleep(3);
//printf("D\n");
pthread_mutex_unlock(myMutex);
//printf("E\n");
myMutex = nextLine(CITY_B, train->to);
//printf("F\n");
printf("Train: %d\tLine: %s\tFrom: %s\tTo: %s\n", train->num,
getLineName(CITY_B, train->to), getCityName(train->from), getCityName(train->to));
// Each line takes x sec to finish
//printf("G\n");
sleep(3);
//printf("H\n");
pthread_mutex_unlock(myMutex);
//printf("I\n");
chegada = hora();
//printf("J\n");
printf("\nTrain: %d\nDeparture: %s\tArrival: %s\n\n", train->num, partida, chegada);
//printf("K\n");
pthread_exit((void*)NULL);
}
int main(char *arg, char **args){
pthread_t threads[TRAIN_NUMBER];
Train trains[TRAIN_NUMBER];
lineAB = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
lineBC = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
lineBD = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
srand(time(NULL));
int i;
for (i = 0; i < TRAIN_NUMBER; ++i) {
trains[i].num = i+1;
trains[i].from = generateRandom(CITY_A, CITY_D, i);
if(trains[i].from == CITY_A) {
trains[i].to = generateRandom(CITY_C, CITY_D, i);
} else {
trains[i].to = CITY_A;
}
pthread_create(&threads[i],NULL,threadFunc,(void*)&trains[i]);
}
for(i = 0; i < TRAIN_NUMBER; i++) {
pthread_join(threads[i], NULL);
}
pthread_mutex_destroy(&lineAB);
pthread_mutex_destroy(&lineBC);
pthread_mutex_destroy(&lineBD);
return 0;
}
Here are some results of the code !
Example 1 (Before printing anything):
make: *** [run] Segmentation fault
Example 2:
Train 1, From: City D, To: City A
Train: 1 Line: cityB-cityD From: City D To: City A
Train 3, From: City D, To: City A
make: *** [run] Segmentation fault
Example 3:
Train 1, From: City A, To: City C
Train: 1 Line: cityA-cityB From: City A To: City C
Train 2, From: City A, To: City C
Train 3, From: City C, To: City A
Train: 3 Line: cityB-cityC From: City C To: City A
Train: 1 Line: cityB-cityC From: City A To: City C
Train: 3 Line: cityA-cityB From: City C To: City A
Train: 2 Line: cityA-cityB From: City A To: City C
Train: 2 Line: cityB-cityC From: City A To: City C
Train: 1 Departure: 18:51:55 Arrival: 18:52:01
Train: 3 Departure: 18:51:55 Arrival: 18:52:01
Train: 2 Departure: 18:51:55 Arrival: 18:52:04
Upvotes: 0
Views: 508
Reputation: 16540
the posted code contains LOTS of problems, most of which are indicated in the comments.
However, the main problem is in the generateRandom()
function at this line:
return ((rand()%max)+min);
which is generating values that are greater than 3 (5 being typical)
Then, later in the code, the access to the mutex array is accessing beyond the end of the array.
Then the call to pthread_mutex_lock()
is being fed an invalid pointer, resulting in the seg fault event.
Two passes with the gdb
debugger along with some 'useful' calls to printf()
quickly located the source of the problem.
Strongly suggest you become very familiar with a debugger.
here is the version of the code that I used for debugging:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> // rand(), srand()
#include <unistd.h>
// Not order for easy random implementation
#define CITY_B 1
#define CITY_A 2
#define CITY_C 3
#define CITY_D 4
#define TRAIN_NUMBER 3
pthread_mutex_t lineAB = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lineBC = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lineBD = PTHREAD_MUTEX_INITIALIZER;
struct TrainStruct
{
size_t num;
size_t from;
size_t to;
};
typedef struct TrainStruct Train;
size_t generateRandom(int min, int max, size_t seed)
{
(void)seed;
//srand(time(NULL)+seed);
return (size_t)((rand()%max)+min);
}
char * getCurrentTime()
{
char * timeString = malloc(20);
time_t now = time(NULL);
strftime(timeString, 20, "%H:%M:%S", localtime(&now));
return timeString;
} // end function: getCurrentTime
char * hora() {
return getCurrentTime();
}
pthread_mutex_t * nextLine(size_t from, size_t to)
{
switch(from)
{
case CITY_A:
return &lineAB;
break;
case CITY_B:
switch(to)
{
case CITY_A:
return &lineAB;
break;
case CITY_C:
return &lineBC;
break;
case CITY_D:
return &lineBD;
break;
default:
printf( "invalid train.to: %lu\n", to);
return NULL;
break;
} // end switch
break;
case CITY_C:
return &lineBC;
break;
case CITY_D:
return &lineBD;
break;
default:
printf( "invalid train.from: %lu\n", from);
return NULL;
break;
} // end switch
}
char * getCityName(size_t num)
{
switch(num)
{
case CITY_A:
return "City A";
break;
case CITY_B:
return "City B";
break;
case CITY_C:
return "City C";
break;
case CITY_D:
return "City D";
break;
default:
printf( "invalid city num: %lu\n", num);
return NULL;
break;
} // end switch
}
char * getLineName( size_t from, size_t to)
{
switch(from)
{
case CITY_A:
return "cityA-cityB";
break;
case CITY_B:
switch(to)
{
case CITY_A: {
return "cityA-cityB";
break;
}
case CITY_C:
return "cityB-cityC";
break;
case CITY_D:
return "cityB-cityD";
break;
default:
printf( "invalid train.to: %lu\n", to);
return NULL;
break;
} // end switch
break;
case CITY_C:
return "cityB-cityC";
break;
case CITY_D:
return "cityB-cityD";
break;
default:
printf( "invalid train.from: %lu\n", from);
return NULL;
break;
} // end switch
}
void * threadFunc(void *arg)
{
Train * train = (Train*)arg;
/*int trainNum = info[0];
int from = info[1];
int to = info[2];*/
char * partida = hora();
char * chegada;
// for testing
printf( "func:%s\n num: %lu\n from: %lu\n to: %lu\n\n",
__func__,
train->num,
train->from,
train->to);
printf("Train %lu, From: %s, To: %s\n\n",
train->num,
getCityName(train->from),
getCityName(train->to));
//printf("A\n");
pthread_mutex_t * myMutex = nextLine(train->from, CITY_B);
pthread_mutex_lock(myMutex);
//printf("B\n");
printf("Train: %lu\tLine: %s\tFrom: %s\tTo: %s\n",
train->num,
getLineName(train->from, CITY_B),
getCityName(train->from),
getCityName(train->to));
// Each line takes x sec to finish
//printf("C\n");
sleep(3);
//printf("D\n");
pthread_mutex_unlock(myMutex);
//printf("E\n");
myMutex = nextLine(CITY_B, train->to);
//printf("F\n");
printf("Train: %lu\tLine: %s\tFrom: %s\tTo: %s\n",
train->num,
getLineName(CITY_B, train->to),
getCityName(train->from),
getCityName(train->to));
// Each line takes x sec to finish
//printf("G\n");
sleep(3);
//printf("H\n");
pthread_mutex_unlock(myMutex);
//printf("I\n");
chegada = hora();
//printf("J\n");
printf("\nTrain: %lu\nDeparture: %s\tArrival: %s\n\n",
train->num,
partida,
chegada);
//printf("K\n");
pthread_exit((void*)NULL);
}
int main( void )
{
pthread_t threads[TRAIN_NUMBER];
Train trains[TRAIN_NUMBER];
srand((unsigned)time(NULL));
for (size_t i = 0; i < TRAIN_NUMBER; ++i)
{
trains[i].num = i+1;
trains[i].from = generateRandom(CITY_A, CITY_D, i);
if(trains[i].from == CITY_A)
{
trains[i].to = generateRandom(CITY_C, CITY_D, i);
}
else
{
trains[i].to = CITY_A;
}
pthread_create(&threads[i],NULL,threadFunc,(void*)&trains[i]);
}
for(size_t i = 0; i < TRAIN_NUMBER; i++)
{
pthread_join(threads[i], NULL);
}
pthread_mutex_destroy(&lineAB);
pthread_mutex_destroy(&lineBC);
pthread_mutex_destroy(&lineBD);
} // end function: main
Upvotes: 0
Reputation: 5125
I ran the program with
ulimit -c unlimited
this caused a core file to be generated. Now whe can run gdb.
Debugging this core file shows the error is at this line:
printf("Train %d, From: %s, To: %s\n", train->num, getCityName(train->from), getCityName(train->to));
Printing train gives:
(gdb) print *train
$3 = {num = 3, from = 5, to = 2}
So train->from is invalid (valid is 1-4)!
train->to and train->from is generated with generateRandom(), so the bug must be here.
int generateRandom(int min, int max, int seed) {
srand(time(NULL)+seed);
return ((rand()%max)+min);
}
rand()%max can generate number from 0 to max-1. Adding min to this can give max+min-1. Since inputs are 2 (CITY_A) and 4 (CITY_D) you can get numbers between 2 and 5. You probably want this instead:
int generateRandom(int min, int max, int seed) {
srand(time(NULL)+seed);
return ((rand()%(max-min))+min);
}
Upvotes: 1