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,¶m);
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