rschirin
rschirin

Reputation: 2049

pthread_join blocks my code

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

Answers (1)

David Schwartz
David Schwartz

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

Related Questions