0

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;
 }

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

8 Comments

You definitely cannot hold a mutex across the fork and unlock it in the child, because only the thread which locked the mutex is allowed to unlock it. Anything else results in undefined behavior (or an error if it's an error-checking mutex).
Also note that, per POSIX: "If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called."
by the way, I'm trying to use atfork() with prepare that locks mutex,parent that unlock it and child too, but the result is the same. Using pthread_join it doesn't work.
@R.. Are you saying me that I cannot do that?neither with pthread_atfork()? I modified code, using it, but no great changes.
Your code tries to join id[0], which doesn't correspond to any thread you actually created.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.