I'm playing around with a solution for the dinning philosophers problem using mutexes, however the program is segfaulting for probably a thread-related bug
What i'm trying to do here is basically think of the fork as a mutex and creat a function void *eat(void *arg)
, and then close the critical section (the critical section is just the thread declaring its id and that its currently eating) whatever the function gets called , then i loop through all my philosophers and check if its id (id's start from 0) divisible by 2.
First round just threads id's that are divisible by 2 eat and second round only threads id's that are not will eat and so on in an infinite loop .
I know this a stupidly simple solution which probably doesn't solve the problem in the first place. so please bear with me. if you have any questions please let me know in the comment.
struct typedef t_philo
{
pthread_t thread;
pthread_mutex_t fork;
int id;
}
t_philo;
void *eat(void *arg)
{
t_philo *philo = (t_philo *)arg;
pthread_mutex_lock(&philo->fork);
printf("philo with id: %i is eating\n", philo->id);
pthread_mutex_unlock(&philo->fork);
return (NULL);
}
void first_round(t_philo *philo, int len)
{
for (int i = 0; i < len; i )
if (!(i % 2))
pthread_join(philo[i].thread, NULL);
}
void second_round(t_philo *philo, int len)
{
for (int i = 0; i < len; i )
if ((i % 2))
pthread_join(philo[i].thread, NULL);
}
int main(int argc, char **argv)
{
t_philo *philo;
// how many philosophers is given as first arg.
int len = atoi(argv[1]);
if (argc < 2)
exit(EXIT_FAILURE);
philo = malloc(sizeof(*philo) * atoi(argv[1]));
//this function add id's and initialize some data.
init_data(philo, argv);
for (int i = 0; i < len; i )
pthread_create(&philo[i].thread, NULL, eat(&philo[i]), &philo[i]);
while (1)
{
first_round(philo, len);
second_round(philo, len);
}
return 0;
}
OUTPUT
philo with id: 0 is eating
philo with id: 1 is eating
philo with id: 2 is eating
philo with id: 3 is eating
philo with id: 4 is eating
.
.
.
.
philo with id random is eating
[1] 29903 segmentation fault
Output reaches a random id each time and segfault, that's why i concluded it might be a thread bug.
CodePudding user response:
pthread_create
has this following prototype:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
start_routine
is a function pointer. However, you call pthread_create
with wrong arguments: eat(&philo[i])
. Thus, the program calls eat
correctly and then tries to call NULL
(from a new thread) because this is the value returned by eat
. The randomness comes from the variable time to actually create the threads.
Note that using a debugger should help you to find and fix the problem very easily. Debuggers like gdb are a bit hard to learn but once this is done, errors like segfault becomes almost easy to fix. I am also surprised a compiler like clang would not notice the typing issue at compile time.
CodePudding user response:
In main
, int len = argv[1];
is wrong. If you compiled with warnings enabled (e.g. -Wall
), this statement would be flagged by the compiler.
As is, you're getting a huge value for len
. So, later, the for
loop will overflow the array you allocate and you have UB.
You probably want: int len = atoi(argv[1]);
as you have for the malloc
.
And, you want to do this after the argc
check.
And, why call atoi
twice [with the fix]?
Here's the refactored code:
int
main(int argc, char **argv)
{
t_philo *philo;
if (argc < 2)
exit(EXIT_FAILURE);
// how many philosophers is given as first arg.
int len = atoi(argv[1]);
philo = malloc(sizeof(*philo) * len);
// do stuff ...
return 0;
}