Reputation: 2049
can you explain me why the following use of pthread_join doesn't work?it blocks my code. if I comment those 3 lines, my code does what is expected, but obviously I don't know if threads are terminated(in my code there is no problem for that, but in a bigger situation there is).
int k=0;
pthread_mutex_t mutex= PTHREAD_MUTEX_INITIALIZER;
struct primi{
int s;
int temp;
};
struct example{
int c;
struct primi primissimi;
};
void *funzione_thread(void* args);
void prepare(void){
printf("preparing locks...\n");
pthread_mutex_lock(&mutex); }
void parent(void){
printf("parent unlocking locks...\n");
pthread_mutex_unlock(&mutex);}
void child(void){
printf("child unlocking locks...\n");
pthread_mutex_unlock(&mutex); }
void *thr_fn(void *arg){
printf("thread started...\n");
return(0);}
void *funzione_thread(void* args){
pthread_mutex_lock(&mutex);
struct example *exthread = args;
struct example locale = *exthread;
locale.primissimi.s++;pthread_mutex_unlock(&mutex);
printf("local is %d original is %d\n",locale.primissimi.s,exthread->primissimi.s);
exthread->primissimi.s = locale.primissimi.s;
printf("after it is%d\n",exthread->primissimi.s);
pthread_exit(NULL);
}
int ffork(struct example *extmp){
pthread_t id[5];
int i;
while(k<3){
k++;
pthread_create(&id[k],NULL,funzione_thread,extmp);
}
printf("now k is %d\n\n",k);
for(i=1;i<=3;i++){
pthread_join( id[i] ,NULL );
printf("waited thread %d\n",i);
}
printf("threads completed\n");
pthread_exit (NULL);
//return 1;
}
int main(int argc, char** argv){
struct example *ex = malloc(sizeof(*ex));
int pid,tmp;
pthread_t tid;
if ((err = pthread_atfork(prepare, parent, child)) != 0){
printf("can't install fork handlers");
exit(-1);}
pthread_create(&tid, NULL, thr_fn, 0);
sleep(1);
pid=fork();
if(pid==0){
ex->c=1;
ex->primissimi.s=1;
if((tmp=ffork(ex))!=1){
printf("errore in ffork\n");
sleep(2);
exit(0);
}
else{printf("tutto ok in ffork\n");
sleep(2);
exit(0);
}
}//fine figlio
else{
sleep(10);
}
return 0;
}
Upvotes: 0
Views: 2974
Reputation: 182761
Your code has no protection against calling fork
with the mutex locked. Since the thread that locked the mutex doesn't exist in the child, it cannot unlock the mutex ... ever. Any thread in the child that tries to acquire the mutex will deadlock, waiting for the non-existent thread to release the lock.
There are a lot of possible fixes, but the simplest is probably to hold the mutex across the call to fork
. You can use an atfork handler to do this. Arrange the handler to acquire the mutex before the fork
and release it after (in both the parent and child).
You really need to know what you're doing to use fork
together with pthreads, unless you're going to immediately exec
in the child.
Upvotes: 1