2

I have a basic question on mutext handling. I have a file which appears at 2 other threads(out of 3). I need to mutually exclude access to it by a thread. So I do the following in a function called from the thread1 handler:

int sub_routine_thread1{

pthread_mutex_lock(&mut)
FILE *fp;
fp = fopen("myfile", "r");
if(fp == NULL){
return -1;
}
pthread_mutex_unlock(&mut)
return 0;
}

As you can see I already know that if the file pointer return a NULL, then my mutex gets locked here and the unlocking never happens. So I changed it to the following:

int sub_routine_thread1{

pthread_mutex_lock(&mut)
FILE *fp;
fp = fopen("myfile", "r");
if(fp == NULL){
   pthread_mutex_unlock(&mut)
   return -1;
}
pthread_mutex_unlock(&mut)
return 0;
}

But after this though I have a bad feeling this is not the way mutex locking should be done. I chanced upon something about cleanup handlers and perhaps thought this is how I must code:

int sub_routine_thread1{
     pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
     pthread_mutex_lock(&mut);
     FILE *fp;
     fp = fopen("myfile", "r");
     if(fp == NULL){
     return -1;
     }
     pthread_cleanup_pop(1);
     return 0;
}

Is this the right way? Can you please clarify?

user489152
  • 907
  • 1
  • 23
  • 42
  • What do you want to protect against? Another thread writing to the file while you read from it? What is the minimum unit of work on the file that should be atomic? Reading some binary struct from the file? Reading a line? Reading the last line of the file? Reading the whole file? – ninjalj Jul 15 '11 at 18:28

2 Answers2

1

First of all

if(fp == NULL){
    return -1;
    pthread_mutex_unlock(&mut); /* This is never reached. */
}

if(fp == NULL){
    pthread_mutex_unlock(&mut); /* Probably what you want. */
    return NULL;
}

Second, cleanup handlers are really really cool and useful, but they are only called when you cancel the thread using pthread_cancel. They are not called when the thread exits normally (and that return is considered normal).

cnicutar
  • 178,505
  • 25
  • 365
  • 392
1

But after this though I have a bad feeling this is not the way mutex loxking should be done.

Yes it is. Your second example is perfectly fine. pthread_cleanup_push is used to run functions when the thread is cancelled, that's not what you should use here.

Allthough, I'd probably prefer to do something like

int sub_routine_thread1() {
  FILE *fp;
  int ret = -1;
  pthread_mutex_lock(&mut)
  fp = fopen("myfile", "r");
  if(fp != NULL){
     //do_stuff_unlocked(fp);
     ret = 0;
  }
  pthread_mutex_unlock(&mut)
  return ret;
}
nos
  • 223,662
  • 58
  • 417
  • 506