I have the following function that will run in the thread:
void *dinning_handler(void *arg)
{
t_philo *philo;
struct timeval start;
philo = (t_philo *)arg;
gettimeofday(&start, NULL);
philo->last_meal_time = start;
while (philo->max_eats == -1 || philo->eats < philo->max_eats)
{
print_blue("is thinking", philo->id, get_ts_in_ms());
pthread_mutex_lock(philo->left_fork);
pthread_mutex_lock(philo->right_fork);
print_blue("has taken a fork", philo->id, get_ts_in_ms());
print_green("is eating", philo->id, get_ts_in_ms());
usleep(philo->time_to_eat * 1000);
philo->eats++;
gettimeofday(&philo->last_meal_time, NULL);
pthread_mutex_unlock(philo->left_fork);
pthread_mutex_unlock(philo->right_fork);
print_blue("is sleeping", philo->id, get_ts_in_ms());
usleep(philo->time_to_sleep * 1000);
}
return (NULL);
}
each of the print functions will have the following format:
void print_red(char **msg, int id, long time)
{
ft_printf("\033[1;31m");
ft_printf("%u %d %s\n", time, id, msg);
ft_printf("\033[0m");
}
This generate a race condition leading to write wrong values in the terminal. If I replace ft_print(which is a self implementation that suppose to work the same way of printf) for the original printf it works fine. Why? do printf use mutex before print? how can I fix my code?
EDIT:
Link for ft_printf implementation, it is too big to put it here
If I replace ft_print for the original printf it works fine. Why?
POSIX requires printf
to be thread-safe.
But a sequence of printf
statements is not atomic, so you also got lucky.
You need to ensure the group of printf
calls are executed atomically. In this case, the best solution is to combine them into one.
printf(
"\033[1;31m"
"%u %d %s\n"
"\033[0m",
time, id, msg
);
how can I fix my code?
As with printf
, you need to make the group of calls to ft_printf
atomic. Yes, you could use a mutex to achieve this.
// Lock the mutex here.
ft_printf( "\033[1;31m" );
ft_printf( "%u %d %s\n", time, id, msg );
ft_printf( "\033[0m" );
// Unlock it here.