The following code is a simple thread game, that switches between threads causing the timer to decrease.
It works fine for 3 threads, causes and Abort(core dumped) for 4 threads, and causes a seg fault for 5 or more threads.
Anyone have any idea why this might be happening?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
int volatile num_of_threads;
int volatile time_per_round;
int volatile time_left;
int volatile turn_id;
int volatile thread_running;
int volatile can_check;
void * player (void * id_in){
int id= (int)id_in;
while(1){
if(can_check){
if (time_left<=0){
break;
}
can_check=0;
if(thread_running){
if(turn_id==id-1){
turn_id=random()%num_of_threads;
time_left--;
}
}
can_check=1;
}
}
pthread_exit(NULL);
}
int main(int argc, char *args[]){
int i;
int buffer;
pthread_t * threads =(pthread_t *)malloc(num_of_threads*sizeof(pthread_t));
thread_running=0;
num_of_threads=atoi(args[1]);
can_check=0;
time_per_round = atoi(args[2]);
time_left=time_per_round;
srandom(time(NULL));
//Create Threads
for (i=0;i<num_of_threads;i++){
do{
buffer=pthread_create(&threads[i],NULL,player,(void *)(i+1));
}while(buffer == EAGAIN);
}
can_check=1;
time_left=time_per_round;
turn_id=random()%num_of_threads;
thread_running=1;
for (i=0;i<num_of_threads;i++){
assert(!pthread_join(threads[i], NULL));
}
return 0;
}
See below on why you should not depend on
volatilein pthreads. However, your specific problem is probably because you malloc your pthread array, based on thenum_of_threadsvariable before you’ve actually setnum_of_threadfromargv[]:So there’s a very good chance you’re writing beyond the end of the
threadsarray. Thenum_of_threadsvariable will probably be zero on start-up which means you’re not allocating what you think you are. Move the allocation to after the extraction of the arguments and that should fix it.And now, for your viewing pleasure :-), my original rant on the unsafe use of
volatile, which I still stand by.Do not rely on
volatileto protect your shared variables. The correct way to do this is with thepthread_mutex_blab_blah_blahcalls.Of particular note, examine this code segment:
URK!!is the point where your current thread may be switched out and another run, leading to the possibility that two threads can be running a critical section of code.My advice is to forget the
can_checkaltogether and just protect all the shared variables with a mutex, something like (from memory):Then put at file-level:
and, in main, before starting any other threads:
Oh yeah, although I haven’t done it, you should also check the return codes for all those mutex calls. I’m not going to add that since it’ll clog up the answer with unnecessary detail, but it’s good practice.