Avoiding deadlock with mutex trylock in multithreaded app.

Pierre Mallard mallard.pierre@gmail.com
Sun Aug 9 12:08:00 GMT 2009


Thanks for your help Rémi

>Generally speaking you should avoid holding locks while entering a callback.
>Copy the callback parameters to the stack, release your lock, invoke the
>callback, and acquire your lock again. Alternatively, use a recursive lock.
>Either way, be careful that the lock-protected state might have changed in the
>mean time.

Following your advice, I found a solution that please me :
In A unregister does not tell A thread the current request is to be
removed. Instead it returns to caller telling it should wait callback
end.
In this case the release function set a boolean for the callback to
stops and cond_wait for the callback to say it stops.
This is OK for me because the first thing I do in the callback is to
know whether I should stop or not. In such a case I cond_signal and
get a new request in A.
I posted the new code at the end.

Still a question in this code. I saw that when my callback was
sleeping to simulate processing, i can not get the lock on B's mutex
in release. I have added a sched_yield after each call to callback in
A but still I have some callback calls that keep locking. The only
things that help was to add a sleep instead of sched_yield. Is there
anyway to better handle this problem ?.

Here is a little program that show the problem :
*******************************************************************************************************
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
volatile int stop = 0;
pthread_t thread;
void * task(void * dummy)
{
  while (!stop){
    pthread_mutex_lock(&mutex);
    fprintf(stderr,"%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
    /* I keep locking if I sleep there */
    sleep(1);
    fprintf(stderr,"%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
    pthread_mutex_unlock(&mutex);
  }
  pthread_exit(0);
}

int main(){

  pthread_create(&thread,NULL,&task,NULL);
  /*   sleep(1); */
  struct sched_param param; int policy;
  pthread_getschedparam(pthread_self(),&policy,&param);
  sleep(1);
  fprintf(stderr,"%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
  pthread_mutex_lock(&mutex);
  fprintf(stderr,"%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
  stop = 1;
  pthread_mutex_unlock(&mutex);
  return 0;
}
*************************************************************************************************

>By the way, your code is buggy. If thread cancellation is acted upon from
>within fprintf() or from within the callback, the lock will stale.

I am not really familiar with pthread_cancel (It was my first time,...
!), I red somewhere that glibc does not yet conform to POSIX on this
point (i.e. none glibc function are cancelation point). Anyway I will
be more carefull next time (I have revert to my old boolean stop in A
context ;) )
I noticed also a wrong copy/paste in main for B's initialisation : the
first one is called on an unitialised table index. It is removed in
new code.

Regards,
-- 
Pierre Mallard
-------------- next part --------------
A non-text attachment was scrubbed...
Name: wait_for_end.c
Type: text/x-csrc
Size: 4881 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-help/attachments/20090809/02691ede/attachment.bin>


More information about the Libc-help mailing list