public inbox for pthreads-win32@sourceware.org
 help / color / mirror / Atom feed
* RE: problem using pthread_cancel and pthread_mutex_lock
@ 2004-03-09 23:25 Simon Gerblich
  2004-03-10  0:57 ` Will Bryant
  2004-03-10 11:11 ` vc
  0 siblings, 2 replies; 12+ messages in thread
From: Simon Gerblich @ 2004-03-09 23:25 UTC (permalink / raw)
  To: vc; +Cc: pthreads-win32

Hi Viv,

I'm also writing code that we compile with redhat linux and pthreads-win32.

I get around your socket problem by having a tcp network class that does the
read(), write() calls etc.  recv() will return with an error if you call
shutdown()
and close()/closesocket() on the socket.
I have a call to shutdown() and close()/closesocket() in the destructor of
the class.
It works well for us.

Maybe you could call shutdown() and close()/closesocket() instead of
"killing the thread", and the recv() call will return and the thread can
shutdown
cleanly.

Simon

> -----Original Message-----
> From:	vc [SMTP:vcotirlea1@hotmail.com]
> Sent:	Wednesday, March 10, 2004 12:38 AM
> To:	rpj@callisto.canberra.edu.au
> Cc:	pthreads-win32@sources.redhat.com
> Subject:	Re: problem using pthread_cancel and pthread_mutex_lock
> 
> Hi Ross,
> 
> Thanks a lot for your answer.
> 
> The application that I'm talking about is a Linux application that needs
> to be ported on Windows. The reason why this app is using the async
> cancelation
> is that if for instance a thread is doing a read() from a socket where
> nothing
> is written this read() will block indefinitelly. Because of this we have a
> so called
> "thread monitor" that is killing the threads that are not responding for a
> long time.
> In the case I explained above if I use cancel deferred this thread will
> never be killed
> as it never gets to a cancelation point.
> 
> I know that a thread shouldn't hang, but this is a cpomplex application
> and
> you never know,
> that is why the thread monitor was implemented.
> 
> I will talk to my Linux coleagues and let's see if we can come up with a
> solution. If not,
> is it ok if I just change the pthread lib as I described in my previous
> email? Or I could broke something?
> 
> Changes that I would make:
> In pthread_mutex_lock calling at the begining
> pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
> and at the end:
> pthread_setcanceltype(oldtype, NULL); //put back
> 
> As the pthread_setcanceltype calls also pthread_mutex_lock => recursivity,
> I
> would add a param to pthread_mutex_lock
> so that when it is called from the pthread_setcanceltype those 2 calls are
> not made ....
> 
> What do you say?
> 
> Thanks in advance,
> Viv
> 
> 
> ----- Original Message -----
> From: "Ross Johnson" <rpj@callisto.canberra.edu.au>
> To: "vc" <vcotirlea1@hotmail.com>
> Cc: <pthreads-win32@sources.redhat.com>
> Sent: Friday, March 05, 2004 12:14 AM
> Subject: Re: problem using pthread_cancel and pthread_mutex_lock
> 
> 
> > Hi VC,
> >
> > I saw you're original post and the response that you got advising
> > against async cancelation, etc, which I would urge you to consider
> > further, even if you need to redesign your application.
> >
> > There is another reason to avoid async cancelation that is specific to
> > pthreads-win32: this implementation only approximates async cancelation
> > because it relies on the thread actually running at some point after
> > cancelation. So if your thread is blocked on a resource at the time that
> > it's async canceled, it won't actually exit until it's unblocked in some
> > way to resume execution (at which point it will exit immediately) - and
> > if you can do that then you don't need async cancelation anyway.
> > Unfortunately, the time you're most likely to really need an async
> > cancel - to kill a thread blocked on a system resource that you can't
> > unblock - is the very time it won't work in pthreads-win32, and if it
> > did work, as in does in other implementations, then you'd probably be
> > creating a resource leak. So it's hard to find a good argument for async
> > cancel.
> >
> > If you were to list the situations where your threads could possibly
> > hang, then you'd probably find that there's a solution for each
> instance.
> >
> > Re switching cancel state within the library:-
> > There are places in the library that temporarily suspend cancelability
> > for cancel safety, usually because the standard requires it, but mutexes
> > are not one of them, for the simple reason that, for the vast majority
> > of cases, it isn't needed, while speed is, and for those rare cases that
> > do need it, programmers can employ solutions similar to the one you've
> > chosen.
> >
> > A few more suggestions:
> > If you're using mutexes to control access to resources that could hang
> > your application then maybe semaphores would be more appropriate - they
> > are not owned by any thread and sem_wait() is a defined [deferred]
> > cancelation point. There is also pthread_testcancel(), which you can use
> > to create your own [deferred] cancelation points.
> >
> > There are also timed versions of all of the synchronisation objects:
> > pthread_mutex_timedlock(), sem_timedwait(),
> > pthread_rwlock_timedrdlock(), pthread_rwlock_timedwrlock(), and
> > pthread_cond_timedwait(); that you can perhaps exploit in your attempts
> > to avoid canceling threads at all.
> >
> > Hope that helps.
> >
> > Regards.
> > Ross
> >
> > vc wrote:
> >
> > >Hi all,
> > >
> > >I found a solution to the problem I have described (see below my orig
> email)
> > >and I'm wondering if this is ok ...
> > >
> > >In my program I have to use asynchronous cancellation as I have
> something
> > >called a "thread monitor" and
> > >if one thread hangs I want after a while my thread monitor to kill it
> > >regardless of where that
> > >thread hanged. Using asynchronous cancellation makes problems (as I
> > >discovered until now)
> > >only when a thread is in a pthread_mutex_lock call, as in that case, by
> > >canceling the thread
> > >the mutex is in an unusable state.
> > >
> > >So what I have done is like this (see below): just before calling the
> > >pthread_mutex_lock
> > >I change the cancellation to deferred cancellation then call the
> > >pthread_mutex_lock and then set back
> > >the original cancellation mode:
> > >
> > >void reader_function (void *arg )
> > >{
> > >
> > > pthread_cleanup_push(cleanup_routine, (void *) &test_data);
> > >
> > > retval = pthread_detach (pthread_self());
> > >
> > > pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
> > > pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
> > >
> > > retval = protect_code_with_mutex_deferred();
> > > pthread_cleanup_pop(1);
> > >
> > > pthread_exit(NULL);
> > >}
> > >
> > >int protect_code_with_mutex_deferred(void)
> > >{
> > > int oldtype = 0;
> > >
> > > pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
> > > retval = pthread_mutex_lock(&my_mutex);
> > > pthread_setcanceltype(oldtype, NULL); //put back
> > > [...]
> > >}
> > >
> > >This seems to work just fine and seems to solve my problem. As I'm
> generaly
> > >using asynchronous cancellation
> > >my thread can be killed at any point and when a pthread_mutex_lock is
> done
> > >because I switch
> > >to deferred cancellation I can be sure that my thread will first go out
> from
> > >the pthread_mutex_lock
> > >call and then it will be canceled, so in my cleanup fction I can do an
> > >unlock of the mutex.
> > >
> > >But I am wondering why this way of solving the problem was not added to
> the
> > >pthread library? Am I missing something?
> > >Is something wrong here? Am I overseen something?
> > >
> > >If no, then in the pthread library in the pthread_mutex_lock at the
> > >beginning the:
> > > pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); could be
> called
> > >and at the end the:
> > > pthread_setcanceltype(oldtype, NULL);
> > >could be called.
> > >Of course some other changes are needed as pthread_setcanceltype calls
> also
> > >pthread_mutex_lock, but for internal use, I mean within the library the
> > >pthread_mutex_lock
> > >could be used with one more param, so that when pthread_mutex_lock is
> called
> > >from within the lib these
> > >2 lines will never be executed.
> > >
> > >Any feedback would be appreciated.
> > >Thanks a lot,
> > >Viv
> > >
> > >
> > >----- Original Message -----
> > >From: "vc" <vcotirlea1@hotmail.com>
> > >To: <pthreads-win32@sources.redhat.com>
> > >Sent: Monday, February 23, 2004 6:45 PM
> > >Subject: problem using pthread_cancel and pthread_mutex_lock
> > >
> > >
> > >
> > >
> > >>Hi all,
> > >>
> > >>I am using the pthread library and I'm having a problem while using
> > >>pthread_cancel and pthread_mutex_lock.
> > >>Problem description:
> > >>I start 2 threads: thread1 and thread2.
> > >>thread1 is doing a pthread_mutex_lock(&mutex), then sleeps for 5 secs
> and
> > >>then it is doing
> > >>a pthread_cancel for the thread2, then is doing a
> > >>pthread_mutex_unlock(&mutex)
> > >>Thread2 is doing a pthread_mutex_lock(&mutex), where it stays as the
> mutex
> > >>is owned
> > >>by the thread1, and at this point the cancel is called.
> > >>Even if in the cleanup procedure of the thread2 I'm doing an
> > >>pthread_mutex_unlock or
> > >>not, next time when the thread1 is trying a pthread_mutex_lock(&mutex)
> it
> > >>will block
> > >>and never gets the mutex.
> > >>Also the pthread_mutex_unlock(&mutex)  for the thread2 in the cleanup
> > >>function fails
> > >>(ret value is 1)
> > >>
> > >>So, my question is: how can a thread cleanly cancel another thread
> which
> > >>
> > >>
> > >is
> > >
> > >
> > >>waiting in a 'pthread_mutex_lock' call, so that this mutex is
> available
> > >>again ?
> > >>
> > >>Here is a sample program:
> > >>====================
> > >>
> > >>#include <windows.h>
> > >>#include <stdio.h>
> > >>#include <stdlib.h>
> > >>#include <pthread.h>
> > >>#include <errno.h>
> > >>
> > >>void cleanup_routine(void *arg);
> > >>void reader_function(void *arg);
> > >>void monitor(void *arg);
> > >>int global_counter=0;
> > >>
> > >>pthread_mutex_t my_mutex;
> > >>int id[2];
> > >>pthread_t reader[2];
> > >>int cancel_mode;
> > >>
> > >>
> > >>int main(int argc, char *argv[])
> > >>{
> > >>   int my_args;
> > >>   int err = 0;
> > >>   cancel_mode = 1;
> > >>
> > >>   printf("We'll try to cancel with mode ASYNCHRONOUS\n");
> > >>
> > >>   id[0] = 1;
> > >>   id[1] = 2;
> > >>   pthread_mutex_init(&my_mutex, NULL);
> > >>
> > >>   my_args = 1;
> > >>   pthread_create( &reader[0], NULL, (void*)&monitor, (void *)
> &my_args);
> > >>   Sleep(2000);
> > >>   my_args = 2;
> > >>   pthread_create( &reader[1], NULL, (void*)&reader_function, (void *)
> > >>&my_args);
> > >>
> > >>   while(1) {
> > >> Sleep(1000);
> > >>   }
> > >>}
> > >>
> > >>void monitor (void *arg )
> > >>{
> > >>   int retval;
> > >>
> > >>   printf("Monitor: Entering monitor routine\n\n");
> > >>
> > >>   printf("Monitor: monitor is locking thread...\n");
> > >>   pthread_mutex_lock(&my_mutex);
> > >>   printf("Monitor: monitor is locking thread - okay\n");
> > >>   Sleep (5000);
> > >>
> > >>   printf("Monitor: monitor kills pthread 0x%x:\n", (unsigned int)
> > >>reader[1]);
> > >>   retval = pthread_cancel (reader[1]);
> > >>   printf("Monitor: kill returns %d\n", retval);
> > >>
> > >>   printf("Monitor: monitor is unlocking thread...\n");
> > >>   pthread_mutex_unlock(&my_mutex);
> > >>   printf("Monitor: monitor is unlocking thread - okay\n");
> > >>
> > >>   printf("Monitor: monitor running\n");
> > >>   Sleep (3000);
> > >>   printf("Monitor: monitor is locking thread...\n");
> > >>   pthread_mutex_lock(&my_mutex); // HERE: it will never get the lock!
> It
> > >>will hang here!
> > >>   printf("Monitor: monitor is locking thread - okay\n");
> > >>
> > >>   Sleep(1000);
> > >>   printf("Monitor: monitor is unlocking thread...\n");
> > >>   pthread_mutex_unlock(&my_mutex);
> > >>   printf("Monitor: monitor is unlocking thread - okay\n");
> > >>}
> > >>
> > >>
> > >>int args;
> > >>
> > >>void reader_function (void *arg )
> > >>{
> > >>   int i=0;
> > >>   int id, state;
> > >>   int retval;
> > >>
> > >>   pthread_cleanup_push(cleanup_routine, NULL);
> > >>   retval = pthread_detach (pthread_self());
> > >>
> > >>   pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
> > >>   printf("Thread: pthread_setcancelstate:   old state was %d\n",
> state);
> > >>
> > >>   if (cancel_mode == 1) {
> > >>       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
> > >>   }
> > >>
> > >>   id = *(int *) arg;
> > >>   printf("Thread: entered thread %d\n", id);
> > >>   printf("Thread: thread returns: 0x%x\n", (unsigned int)
> > >>
> > >>
> > >pthread_self());
> > >
> > >
> > >>   printf("Thread: testthread is locking thread...\n");
> > >>   pthread_mutex_lock(&my_mutex);
> > >>   printf("Thread: testthread is locking thread - okay\n");
> > >>
> > >>   // HERE: it shouldn't come here as the thread will be canceled by
> the
> > >>monitor thread
> > >>   printf("Thread: testthread is unlocking thread...\n");
> > >>   pthread_mutex_unlock(&my_mutex);
> > >>   printf("Thread: testthread is unlocking thread - okay\n");
> > >>
> > >>   printf("Thread: reader_function finished\n");
> > >>
> > >>   pthread_cleanup_pop(0);
> > >>}
> > >>
> > >>
> > >>void cleanup_routine(void *arg)
> > >>{
> > >>   int ret = 0;
> > >>   printf("ThreadCleanup: cleanup called\n");
> > >>   Sleep(5000);
> > >>
> > >>   ret = pthread_mutex_unlock(&my_mutex);
> > >>   printf("ThreadCleanup:Cleanup routine unlock ret = %d\n", ret);
> > >>   printf("ThreadCleanup:waitThread_cleanup done\n");
> > >>}
> > >>
> > >>
> > >>The output looks like:
> > >>=================
> > >>We'll try to cancel with mode ASYNCHRONOUS
> > >>Monitor: Entering monitor routine
> > >>
> > >>Monitor: monitor is locking thread...
> > >>Monitor: monitor is locking thread - okay
> > >>Thread: pthread_setcancelstate:   old state was 0
> > >>Thread: entered thread 2
> > >>Thread: thread returns: 0x312d80
> > >>Thread: testthread is locking thread...
> > >>Monitor: monitor kills pthread 0x312d80:
> > >>Monitor: kill returns 0
> > >>Monitor: monitor is unlocking thread...
> > >>ThreadCleanup: cleanup called
> > >>Monitor: monitor is unlocking thread - okay
> > >>Monitor: monitor running
> > >>Monitor: monitor is locking thread...
> > >>ThreadCleanup:Cleanup routine unlock ret = 1
> > >>ThreadCleanup:waitThread_cleanup done
> > >>
> > >>
> > >>So, from the output can be seen that the 1st thread (called monitor)
> will
> > >>never be able
> > >>to gain the mutex again.
> > >>
> > >>Sorry for the long post,
> > >>Any help will be appreciated,
> > >>Thanks a lot,
> > >>Viv
> > >>
> > >>
> > >>
> >
> >

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-03-09 23:25 problem using pthread_cancel and pthread_mutex_lock Simon Gerblich
@ 2004-03-10  0:57 ` Will Bryant
  2004-03-10 11:11 ` vc
  1 sibling, 0 replies; 12+ messages in thread
From: Will Bryant @ 2004-03-10  0:57 UTC (permalink / raw)
  To: pthreads-win32

Hi Simon,

I've been using this technique in my apps and it works well.

Unfortunately however select() seems to be buggy, from my reading of the
docs it should act exactly the same way, ie. it should return as soon as
the socket is shutdown() - but it doesn't :(.

This is a bit of a problem as it's select as AFAIK only way to get
proper timeout behaviour on Windows...

Will


Simon Gerblich wrote:

>Hi Viv,
>
>I'm also writing code that we compile with redhat linux and pthreads-win32.
>
>I get around your socket problem by having a tcp network class that does the
>read(), write() calls etc.  recv() will return with an error if you call
>shutdown()
>and close()/closesocket() on the socket.
>I have a call to shutdown() and close()/closesocket() in the destructor of
>the class.
>It works well for us.
>
>Maybe you could call shutdown() and close()/closesocket() instead of
>"killing the thread", and the recv() call will return and the thread can
>shutdown
>cleanly.
>
>Simon
>  
>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-03-09 23:25 problem using pthread_cancel and pthread_mutex_lock Simon Gerblich
  2004-03-10  0:57 ` Will Bryant
@ 2004-03-10 11:11 ` vc
  1 sibling, 0 replies; 12+ messages in thread
From: vc @ 2004-03-10 11:11 UTC (permalink / raw)
  To: Simon Gerblich; +Cc: pthreads-win32

Hi Simon,

Thanks for your reply. It's indeed a solution for the problem I have
described,
but it was just a sample with reading from a socket ... It might be
anything.
It can be for instance a bug in our code where there is an infinite loop, or
something similar. For these cases the thread monitor was designed. Of
course, normaly
this shouldn't happen, the threads shouldn't hang and the thread monitor
shouldn't
need to kill any thread. But as we could have some situations where a thread
is not answering for a big period of time, we needed an 'agressiv' solution
on this,
and the thread monitor was the chosen one.

Thx,
Viv

----- Original Message -----
From: "Simon Gerblich" <sgerblich@daronmont.com.au>
To: "vc" <vcotirlea1@hotmail.com>
Cc: <pthreads-win32@sources.redhat.com>
Sent: Wednesday, March 10, 2004 12:25 AM
Subject: RE: problem using pthread_cancel and pthread_mutex_lock


> Hi Viv,
>
> I'm also writing code that we compile with redhat linux and
pthreads-win32.
>
> I get around your socket problem by having a tcp network class that does
the
> read(), write() calls etc.  recv() will return with an error if you call
> shutdown()
> and close()/closesocket() on the socket.
> I have a call to shutdown() and close()/closesocket() in the destructor of
> the class.
> It works well for us.
>
> Maybe you could call shutdown() and close()/closesocket() instead of
> "killing the thread", and the recv() call will return and the thread can
> shutdown
> cleanly.
>
> Simon
>
> > -----Original Message-----
> > From: vc [SMTP:vcotirlea1@hotmail.com]
> > Sent: Wednesday, March 10, 2004 12:38 AM
> > To: rpj@callisto.canberra.edu.au
> > Cc: pthreads-win32@sources.redhat.com
> > Subject: Re: problem using pthread_cancel and pthread_mutex_lock
> >
> > Hi Ross,
> >
> > Thanks a lot for your answer.
> >
> > The application that I'm talking about is a Linux application that needs
> > to be ported on Windows. The reason why this app is using the async
> > cancelation
> > is that if for instance a thread is doing a read() from a socket where
> > nothing
> > is written this read() will block indefinitelly. Because of this we have
a
> > so called
> > "thread monitor" that is killing the threads that are not responding for
a
> > long time.
> > In the case I explained above if I use cancel deferred this thread will
> > never be killed
> > as it never gets to a cancelation point.
> >
> > I know that a thread shouldn't hang, but this is a cpomplex application
> > and
> > you never know,
> > that is why the thread monitor was implemented.
> >
> > I will talk to my Linux coleagues and let's see if we can come up with a
> > solution. If not,
> > is it ok if I just change the pthread lib as I described in my previous
> > email? Or I could broke something?
> >
> > Changes that I would make:
> > In pthread_mutex_lock calling at the begining
> > pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
> > and at the end:
> > pthread_setcanceltype(oldtype, NULL); //put back
> >
> > As the pthread_setcanceltype calls also pthread_mutex_lock =>
recursivity,
> > I
> > would add a param to pthread_mutex_lock
> > so that when it is called from the pthread_setcanceltype those 2 calls
are
> > not made ....
> >
> > What do you say?
> >
> > Thanks in advance,
> > Viv
> >
> >
> > ----- Original Message -----
> > From: "Ross Johnson" <rpj@callisto.canberra.edu.au>
> > To: "vc" <vcotirlea1@hotmail.com>
> > Cc: <pthreads-win32@sources.redhat.com>
> > Sent: Friday, March 05, 2004 12:14 AM
> > Subject: Re: problem using pthread_cancel and pthread_mutex_lock
> >
> >
> > > Hi VC,
> > >
> > > I saw you're original post and the response that you got advising
> > > against async cancelation, etc, which I would urge you to consider
> > > further, even if you need to redesign your application.
> > >
> > > There is another reason to avoid async cancelation that is specific to
> > > pthreads-win32: this implementation only approximates async
cancelation
> > > because it relies on the thread actually running at some point after
> > > cancelation. So if your thread is blocked on a resource at the time
that
> > > it's async canceled, it won't actually exit until it's unblocked in
some
> > > way to resume execution (at which point it will exit immediately) -
and
> > > if you can do that then you don't need async cancelation anyway.
> > > Unfortunately, the time you're most likely to really need an async
> > > cancel - to kill a thread blocked on a system resource that you can't
> > > unblock - is the very time it won't work in pthreads-win32, and if it
> > > did work, as in does in other implementations, then you'd probably be
> > > creating a resource leak. So it's hard to find a good argument for
async
> > > cancel.
> > >
> > > If you were to list the situations where your threads could possibly
> > > hang, then you'd probably find that there's a solution for each
> > instance.
> > >
> > > Re switching cancel state within the library:-
> > > There are places in the library that temporarily suspend cancelability
> > > for cancel safety, usually because the standard requires it, but
mutexes
> > > are not one of them, for the simple reason that, for the vast majority
> > > of cases, it isn't needed, while speed is, and for those rare cases
that
> > > do need it, programmers can employ solutions similar to the one you've
> > > chosen.
> > >
> > > A few more suggestions:
> > > If you're using mutexes to control access to resources that could hang
> > > your application then maybe semaphores would be more appropriate -
they
> > > are not owned by any thread and sem_wait() is a defined [deferred]
> > > cancelation point. There is also pthread_testcancel(), which you can
use
> > > to create your own [deferred] cancelation points.
> > >
> > > There are also timed versions of all of the synchronisation objects:
> > > pthread_mutex_timedlock(), sem_timedwait(),
> > > pthread_rwlock_timedrdlock(), pthread_rwlock_timedwrlock(), and
> > > pthread_cond_timedwait(); that you can perhaps exploit in your
attempts
> > > to avoid canceling threads at all.
> > >
> > > Hope that helps.
> > >
> > > Regards.
> > > Ross
> > >
> > > vc wrote:
> > >
> > > >Hi all,
> > > >
> > > >I found a solution to the problem I have described (see below my orig
> > email)
> > > >and I'm wondering if this is ok ...
> > > >
> > > >In my program I have to use asynchronous cancellation as I have
> > something
> > > >called a "thread monitor" and
> > > >if one thread hangs I want after a while my thread monitor to kill it
> > > >regardless of where that
> > > >thread hanged. Using asynchronous cancellation makes problems (as I
> > > >discovered until now)
> > > >only when a thread is in a pthread_mutex_lock call, as in that case,
by
> > > >canceling the thread
> > > >the mutex is in an unusable state.
> > > >
> > > >So what I have done is like this (see below): just before calling the
> > > >pthread_mutex_lock
> > > >I change the cancellation to deferred cancellation then call the
> > > >pthread_mutex_lock and then set back
> > > >the original cancellation mode:
> > > >
> > > >void reader_function (void *arg )
> > > >{
> > > >
> > > > pthread_cleanup_push(cleanup_routine, (void *) &test_data);
> > > >
> > > > retval = pthread_detach (pthread_self());
> > > >
> > > > pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
> > > > pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
> > > >
> > > > retval = protect_code_with_mutex_deferred();
> > > > pthread_cleanup_pop(1);
> > > >
> > > > pthread_exit(NULL);
> > > >}
> > > >
> > > >int protect_code_with_mutex_deferred(void)
> > > >{
> > > > int oldtype = 0;
> > > >
> > > > pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
> > > > retval = pthread_mutex_lock(&my_mutex);
> > > > pthread_setcanceltype(oldtype, NULL); //put back
> > > > [...]
> > > >}
> > > >
> > > >This seems to work just fine and seems to solve my problem. As I'm
> > generaly
> > > >using asynchronous cancellation
> > > >my thread can be killed at any point and when a pthread_mutex_lock is
> > done
> > > >because I switch
> > > >to deferred cancellation I can be sure that my thread will first go
out
> > from
> > > >the pthread_mutex_lock
> > > >call and then it will be canceled, so in my cleanup fction I can do
an
> > > >unlock of the mutex.
> > > >
> > > >But I am wondering why this way of solving the problem was not added
to
> > the
> > > >pthread library? Am I missing something?
> > > >Is something wrong here? Am I overseen something?
> > > >
> > > >If no, then in the pthread library in the pthread_mutex_lock at the
> > > >beginning the:
> > > > pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); could be
> > called
> > > >and at the end the:
> > > > pthread_setcanceltype(oldtype, NULL);
> > > >could be called.
> > > >Of course some other changes are needed as pthread_setcanceltype
calls
> > also
> > > >pthread_mutex_lock, but for internal use, I mean within the library
the
> > > >pthread_mutex_lock
> > > >could be used with one more param, so that when pthread_mutex_lock is
> > called
> > > >from within the lib these
> > > >2 lines will never be executed.
> > > >
> > > >Any feedback would be appreciated.
> > > >Thanks a lot,
> > > >Viv
> > > >
> > > >
> > > >----- Original Message -----
> > > >From: "vc" <vcotirlea1@hotmail.com>
> > > >To: <pthreads-win32@sources.redhat.com>
> > > >Sent: Monday, February 23, 2004 6:45 PM
> > > >Subject: problem using pthread_cancel and pthread_mutex_lock
> > > >
> > > >
> > > >
> > > >
> > > >>Hi all,
> > > >>
> > > >>I am using the pthread library and I'm having a problem while using
> > > >>pthread_cancel and pthread_mutex_lock.
> > > >>Problem description:
> > > >>I start 2 threads: thread1 and thread2.
> > > >>thread1 is doing a pthread_mutex_lock(&mutex), then sleeps for 5
secs
> > and
> > > >>then it is doing
> > > >>a pthread_cancel for the thread2, then is doing a
> > > >>pthread_mutex_unlock(&mutex)
> > > >>Thread2 is doing a pthread_mutex_lock(&mutex), where it stays as the
> > mutex
> > > >>is owned
> > > >>by the thread1, and at this point the cancel is called.
> > > >>Even if in the cleanup procedure of the thread2 I'm doing an
> > > >>pthread_mutex_unlock or
> > > >>not, next time when the thread1 is trying a
pthread_mutex_lock(&mutex)
> > it
> > > >>will block
> > > >>and never gets the mutex.
> > > >>Also the pthread_mutex_unlock(&mutex)  for the thread2 in the
cleanup
> > > >>function fails
> > > >>(ret value is 1)
> > > >>
> > > >>So, my question is: how can a thread cleanly cancel another thread
> > which
> > > >>
> > > >>
> > > >is
> > > >
> > > >
> > > >>waiting in a 'pthread_mutex_lock' call, so that this mutex is
> > available
> > > >>again ?
> > > >>
> > > >>Here is a sample program:
> > > >>====================
> > > >>
> > > >>#include <windows.h>
> > > >>#include <stdio.h>
> > > >>#include <stdlib.h>
> > > >>#include <pthread.h>
> > > >>#include <errno.h>
> > > >>
> > > >>void cleanup_routine(void *arg);
> > > >>void reader_function(void *arg);
> > > >>void monitor(void *arg);
> > > >>int global_counter=0;
> > > >>
> > > >>pthread_mutex_t my_mutex;
> > > >>int id[2];
> > > >>pthread_t reader[2];
> > > >>int cancel_mode;
> > > >>
> > > >>
> > > >>int main(int argc, char *argv[])
> > > >>{
> > > >>   int my_args;
> > > >>   int err = 0;
> > > >>   cancel_mode = 1;
> > > >>
> > > >>   printf("We'll try to cancel with mode ASYNCHRONOUS\n");
> > > >>
> > > >>   id[0] = 1;
> > > >>   id[1] = 2;
> > > >>   pthread_mutex_init(&my_mutex, NULL);
> > > >>
> > > >>   my_args = 1;
> > > >>   pthread_create( &reader[0], NULL, (void*)&monitor, (void *)
> > &my_args);
> > > >>   Sleep(2000);
> > > >>   my_args = 2;
> > > >>   pthread_create( &reader[1], NULL, (void*)&reader_function, (void
*)
> > > >>&my_args);
> > > >>
> > > >>   while(1) {
> > > >> Sleep(1000);
> > > >>   }
> > > >>}
> > > >>
> > > >>void monitor (void *arg )
> > > >>{
> > > >>   int retval;
> > > >>
> > > >>   printf("Monitor: Entering monitor routine\n\n");
> > > >>
> > > >>   printf("Monitor: monitor is locking thread...\n");
> > > >>   pthread_mutex_lock(&my_mutex);
> > > >>   printf("Monitor: monitor is locking thread - okay\n");
> > > >>   Sleep (5000);
> > > >>
> > > >>   printf("Monitor: monitor kills pthread 0x%x:\n", (unsigned int)
> > > >>reader[1]);
> > > >>   retval = pthread_cancel (reader[1]);
> > > >>   printf("Monitor: kill returns %d\n", retval);
> > > >>
> > > >>   printf("Monitor: monitor is unlocking thread...\n");
> > > >>   pthread_mutex_unlock(&my_mutex);
> > > >>   printf("Monitor: monitor is unlocking thread - okay\n");
> > > >>
> > > >>   printf("Monitor: monitor running\n");
> > > >>   Sleep (3000);
> > > >>   printf("Monitor: monitor is locking thread...\n");
> > > >>   pthread_mutex_lock(&my_mutex); // HERE: it will never get the
lock!
> > It
> > > >>will hang here!
> > > >>   printf("Monitor: monitor is locking thread - okay\n");
> > > >>
> > > >>   Sleep(1000);
> > > >>   printf("Monitor: monitor is unlocking thread...\n");
> > > >>   pthread_mutex_unlock(&my_mutex);
> > > >>   printf("Monitor: monitor is unlocking thread - okay\n");
> > > >>}
> > > >>
> > > >>
> > > >>int args;
> > > >>
> > > >>void reader_function (void *arg )
> > > >>{
> > > >>   int i=0;
> > > >>   int id, state;
> > > >>   int retval;
> > > >>
> > > >>   pthread_cleanup_push(cleanup_routine, NULL);
> > > >>   retval = pthread_detach (pthread_self());
> > > >>
> > > >>   pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
> > > >>   printf("Thread: pthread_setcancelstate:   old state was %d\n",
> > state);
> > > >>
> > > >>   if (cancel_mode == 1) {
> > > >>       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
> > > >>   }
> > > >>
> > > >>   id = *(int *) arg;
> > > >>   printf("Thread: entered thread %d\n", id);
> > > >>   printf("Thread: thread returns: 0x%x\n", (unsigned int)
> > > >>
> > > >>
> > > >pthread_self());
> > > >
> > > >
> > > >>   printf("Thread: testthread is locking thread...\n");
> > > >>   pthread_mutex_lock(&my_mutex);
> > > >>   printf("Thread: testthread is locking thread - okay\n");
> > > >>
> > > >>   // HERE: it shouldn't come here as the thread will be canceled by
> > the
> > > >>monitor thread
> > > >>   printf("Thread: testthread is unlocking thread...\n");
> > > >>   pthread_mutex_unlock(&my_mutex);
> > > >>   printf("Thread: testthread is unlocking thread - okay\n");
> > > >>
> > > >>   printf("Thread: reader_function finished\n");
> > > >>
> > > >>   pthread_cleanup_pop(0);
> > > >>}
> > > >>
> > > >>
> > > >>void cleanup_routine(void *arg)
> > > >>{
> > > >>   int ret = 0;
> > > >>   printf("ThreadCleanup: cleanup called\n");
> > > >>   Sleep(5000);
> > > >>
> > > >>   ret = pthread_mutex_unlock(&my_mutex);
> > > >>   printf("ThreadCleanup:Cleanup routine unlock ret = %d\n", ret);
> > > >>   printf("ThreadCleanup:waitThread_cleanup done\n");
> > > >>}
> > > >>
> > > >>
> > > >>The output looks like:
> > > >>=================
> > > >>We'll try to cancel with mode ASYNCHRONOUS
> > > >>Monitor: Entering monitor routine
> > > >>
> > > >>Monitor: monitor is locking thread...
> > > >>Monitor: monitor is locking thread - okay
> > > >>Thread: pthread_setcancelstate:   old state was 0
> > > >>Thread: entered thread 2
> > > >>Thread: thread returns: 0x312d80
> > > >>Thread: testthread is locking thread...
> > > >>Monitor: monitor kills pthread 0x312d80:
> > > >>Monitor: kill returns 0
> > > >>Monitor: monitor is unlocking thread...
> > > >>ThreadCleanup: cleanup called
> > > >>Monitor: monitor is unlocking thread - okay
> > > >>Monitor: monitor running
> > > >>Monitor: monitor is locking thread...
> > > >>ThreadCleanup:Cleanup routine unlock ret = 1
> > > >>ThreadCleanup:waitThread_cleanup done
> > > >>
> > > >>
> > > >>So, from the output can be seen that the 1st thread (called monitor)
> > will
> > > >>never be able
> > > >>to gain the mutex again.
> > > >>
> > > >>Sorry for the long post,
> > > >>Any help will be appreciated,
> > > >>Thanks a lot,
> > > >>Viv
> > > >>
> > > >>
> > > >>
> > >
> > >
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-03-09 15:09       ` Panagiotis E. Hadjidoukas
@ 2004-03-09 15:42         ` Brano Kemen
  0 siblings, 0 replies; 12+ messages in thread
From: Brano Kemen @ 2004-03-09 15:42 UTC (permalink / raw)
  To: pthreads-win32

It surely would be more useful than the current async. cancellation code, but would it help in this particular case? If the thread is waiting on a socket, the APC(ex) won't be executed until the thread voluntarily returns from kernel. Am I right?

NtAlertThread does apparently wake the thread up even there, although we tested it just with sockets and sleeps (and pthread's injected cancellation code). 

brk

Panagiotis E. Hadjidoukas wrote:

> In general, don' t you agree that an "official" extension of QueueUserAPC
> (e.g. QueueUserAPCEx, that automatically sets the target thread in alertable
> state)
> would be very useful?
> 
> Panagiotis
> 
> 
> 
> ----- Original Message ----- 
> From: "Brano Kemen" <cameni@manabove.org>
> To: <pthreads-win32@sources.redhat.com>
> Sent: Tuesday, March 09, 2004 4:15 PM
> Subject: Re: problem using pthread_cancel and pthread_mutex_lock
> 
> 
> 
>>
>>Ross Johnson wrote:
>>
>>>There is another reason to avoid async cancelation that is specific to
>>>pthreads-win32: this implementation only approximates async cancelation
>>>because it relies on the thread actually running at some point after
>>>cancelation. So if your thread is blocked on a resource at the time that
>>>it's async canceled, it won't actually exit until it's unblocked in some
>>>way to resume execution (at which point it will exit immediately) - and
>>>if you can do that then you don't need async cancelation anyway.
>>>Unfortunately, the time you're most likely to really need an async
>>>cancel - to kill a thread blocked on a system resource that you can't
>>>unblock - is the very time it won't work in pthreads-win32, and if it
>>>did work, as in does in other implementations, then you'd probably be
>>>creating a resource leak. So it's hard to find a good argument for async
>>>cancel.
>>
>>There's one thing that can help with the blocked threads in windows. It's
> 
> the undocumented "NtAlertThread" function that is exported from ntdll.dll,
> that apparently wakes up the thread even when blocked (listening on socket
> etc.), so it would run the injected cancelation code.
> 
>>We use async cancelation in our project (http://coid.sourceforge.net)
> 
> without problems.
> 
>>On a related note - I think there's bug in pthread_cancel.c in the 'else'
> 
> block starting at line 146. Thread is suspended, and then checked with
> WaitForSingleObject(threadH, 0)  if it did not exit already. But if it did,
> the thread->cancelLock (locked at line 129) is never unlocked back.
> 
>>brk

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-03-09 14:15     ` Brano Kemen
@ 2004-03-09 15:09       ` Panagiotis E. Hadjidoukas
  2004-03-09 15:42         ` Brano Kemen
  0 siblings, 1 reply; 12+ messages in thread
From: Panagiotis E. Hadjidoukas @ 2004-03-09 15:09 UTC (permalink / raw)
  To: pthreads-win32

In general, don' t you agree that an "official" extension of QueueUserAPC
(e.g. QueueUserAPCEx, that automatically sets the target thread in alertable
state)
would be very useful?

Panagiotis



----- Original Message ----- 
From: "Brano Kemen" <cameni@manabove.org>
To: <pthreads-win32@sources.redhat.com>
Sent: Tuesday, March 09, 2004 4:15 PM
Subject: Re: problem using pthread_cancel and pthread_mutex_lock


>
>
> Ross Johnson wrote:
> > There is another reason to avoid async cancelation that is specific to
> > pthreads-win32: this implementation only approximates async cancelation
> > because it relies on the thread actually running at some point after
> > cancelation. So if your thread is blocked on a resource at the time that
> > it's async canceled, it won't actually exit until it's unblocked in some
> > way to resume execution (at which point it will exit immediately) - and
> > if you can do that then you don't need async cancelation anyway.
> > Unfortunately, the time you're most likely to really need an async
> > cancel - to kill a thread blocked on a system resource that you can't
> > unblock - is the very time it won't work in pthreads-win32, and if it
> > did work, as in does in other implementations, then you'd probably be
> > creating a resource leak. So it's hard to find a good argument for async
> > cancel.
>
> There's one thing that can help with the blocked threads in windows. It's
the undocumented "NtAlertThread" function that is exported from ntdll.dll,
that apparently wakes up the thread even when blocked (listening on socket
etc.), so it would run the injected cancelation code.
> We use async cancelation in our project (http://coid.sourceforge.net)
without problems.
>
> On a related note - I think there's bug in pthread_cancel.c in the 'else'
block starting at line 146. Thread is suspended, and then checked with
WaitForSingleObject(threadH, 0)  if it did not exit already. But if it did,
the thread->cancelLock (locked at line 129) is never unlocked back.
>
> brk
>
>
>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-03-04 23:13   ` Ross Johnson
  2004-03-09 14:06     ` vc
@ 2004-03-09 14:15     ` Brano Kemen
  2004-03-09 15:09       ` Panagiotis E. Hadjidoukas
  1 sibling, 1 reply; 12+ messages in thread
From: Brano Kemen @ 2004-03-09 14:15 UTC (permalink / raw)
  To: pthreads-win32



Ross Johnson wrote:
> There is another reason to avoid async cancelation that is specific to 
> pthreads-win32: this implementation only approximates async cancelation 
> because it relies on the thread actually running at some point after 
> cancelation. So if your thread is blocked on a resource at the time that 
> it's async canceled, it won't actually exit until it's unblocked in some 
> way to resume execution (at which point it will exit immediately) - and 
> if you can do that then you don't need async cancelation anyway. 
> Unfortunately, the time you're most likely to really need an async 
> cancel - to kill a thread blocked on a system resource that you can't 
> unblock - is the very time it won't work in pthreads-win32, and if it 
> did work, as in does in other implementations, then you'd probably be 
> creating a resource leak. So it's hard to find a good argument for async 
> cancel.

There's one thing that can help with the blocked threads in windows. It's the undocumented "NtAlertThread" function that is exported from ntdll.dll, that apparently wakes up the thread even when blocked (listening on socket etc.), so it would run the injected cancelation code.
We use async cancelation in our project (http://coid.sourceforge.net) without problems.

On a related note - I think there's bug in pthread_cancel.c in the 'else' block starting at line 146. Thread is suspended, and then checked with  WaitForSingleObject(threadH, 0)  if it did not exit already. But if it did, the thread->cancelLock (locked at line 129) is never unlocked back.

brk

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-03-04 23:13   ` Ross Johnson
@ 2004-03-09 14:06     ` vc
  2004-03-09 14:15     ` Brano Kemen
  1 sibling, 0 replies; 12+ messages in thread
From: vc @ 2004-03-09 14:06 UTC (permalink / raw)
  To: rpj; +Cc: pthreads-win32

Hi Ross,

Thanks a lot for your answer.

The application that I'm talking about is a Linux application that needs
to be ported on Windows. The reason why this app is using the async
cancelation
is that if for instance a thread is doing a read() from a socket where
nothing
is written this read() will block indefinitelly. Because of this we have a
so called
"thread monitor" that is killing the threads that are not responding for a
long time.
In the case I explained above if I use cancel deferred this thread will
never be killed
as it never gets to a cancelation point.

I know that a thread shouldn't hang, but this is a cpomplex application and
you never know,
that is why the thread monitor was implemented.

I will talk to my Linux coleagues and let's see if we can come up with a
solution. If not,
is it ok if I just change the pthread lib as I described in my previous
email? Or I could broke something?

Changes that I would make:
In pthread_mutex_lock calling at the begining
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
and at the end:
pthread_setcanceltype(oldtype, NULL); //put back

As the pthread_setcanceltype calls also pthread_mutex_lock => recursivity, I
would add a param to pthread_mutex_lock
so that when it is called from the pthread_setcanceltype those 2 calls are
not made ....

What do you say?

Thanks in advance,
Viv


----- Original Message -----
From: "Ross Johnson" <rpj@callisto.canberra.edu.au>
To: "vc" <vcotirlea1@hotmail.com>
Cc: <pthreads-win32@sources.redhat.com>
Sent: Friday, March 05, 2004 12:14 AM
Subject: Re: problem using pthread_cancel and pthread_mutex_lock


> Hi VC,
>
> I saw you're original post and the response that you got advising
> against async cancelation, etc, which I would urge you to consider
> further, even if you need to redesign your application.
>
> There is another reason to avoid async cancelation that is specific to
> pthreads-win32: this implementation only approximates async cancelation
> because it relies on the thread actually running at some point after
> cancelation. So if your thread is blocked on a resource at the time that
> it's async canceled, it won't actually exit until it's unblocked in some
> way to resume execution (at which point it will exit immediately) - and
> if you can do that then you don't need async cancelation anyway.
> Unfortunately, the time you're most likely to really need an async
> cancel - to kill a thread blocked on a system resource that you can't
> unblock - is the very time it won't work in pthreads-win32, and if it
> did work, as in does in other implementations, then you'd probably be
> creating a resource leak. So it's hard to find a good argument for async
> cancel.
>
> If you were to list the situations where your threads could possibly
> hang, then you'd probably find that there's a solution for each instance.
>
> Re switching cancel state within the library:-
> There are places in the library that temporarily suspend cancelability
> for cancel safety, usually because the standard requires it, but mutexes
> are not one of them, for the simple reason that, for the vast majority
> of cases, it isn't needed, while speed is, and for those rare cases that
> do need it, programmers can employ solutions similar to the one you've
> chosen.
>
> A few more suggestions:
> If you're using mutexes to control access to resources that could hang
> your application then maybe semaphores would be more appropriate - they
> are not owned by any thread and sem_wait() is a defined [deferred]
> cancelation point. There is also pthread_testcancel(), which you can use
> to create your own [deferred] cancelation points.
>
> There are also timed versions of all of the synchronisation objects:
> pthread_mutex_timedlock(), sem_timedwait(),
> pthread_rwlock_timedrdlock(), pthread_rwlock_timedwrlock(), and
> pthread_cond_timedwait(); that you can perhaps exploit in your attempts
> to avoid canceling threads at all.
>
> Hope that helps.
>
> Regards.
> Ross
>
> vc wrote:
>
> >Hi all,
> >
> >I found a solution to the problem I have described (see below my orig
email)
> >and I'm wondering if this is ok ...
> >
> >In my program I have to use asynchronous cancellation as I have something
> >called a "thread monitor" and
> >if one thread hangs I want after a while my thread monitor to kill it
> >regardless of where that
> >thread hanged. Using asynchronous cancellation makes problems (as I
> >discovered until now)
> >only when a thread is in a pthread_mutex_lock call, as in that case, by
> >canceling the thread
> >the mutex is in an unusable state.
> >
> >So what I have done is like this (see below): just before calling the
> >pthread_mutex_lock
> >I change the cancellation to deferred cancellation then call the
> >pthread_mutex_lock and then set back
> >the original cancellation mode:
> >
> >void reader_function (void *arg )
> >{
> >
> > pthread_cleanup_push(cleanup_routine, (void *) &test_data);
> >
> > retval = pthread_detach (pthread_self());
> >
> > pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
> > pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
> >
> > retval = protect_code_with_mutex_deferred();
> > pthread_cleanup_pop(1);
> >
> > pthread_exit(NULL);
> >}
> >
> >int protect_code_with_mutex_deferred(void)
> >{
> > int oldtype = 0;
> >
> > pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
> > retval = pthread_mutex_lock(&my_mutex);
> > pthread_setcanceltype(oldtype, NULL); //put back
> > [...]
> >}
> >
> >This seems to work just fine and seems to solve my problem. As I'm
generaly
> >using asynchronous cancellation
> >my thread can be killed at any point and when a pthread_mutex_lock is
done
> >because I switch
> >to deferred cancellation I can be sure that my thread will first go out
from
> >the pthread_mutex_lock
> >call and then it will be canceled, so in my cleanup fction I can do an
> >unlock of the mutex.
> >
> >But I am wondering why this way of solving the problem was not added to
the
> >pthread library? Am I missing something?
> >Is something wrong here? Am I overseen something?
> >
> >If no, then in the pthread library in the pthread_mutex_lock at the
> >beginning the:
> > pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); could be
called
> >and at the end the:
> > pthread_setcanceltype(oldtype, NULL);
> >could be called.
> >Of course some other changes are needed as pthread_setcanceltype calls
also
> >pthread_mutex_lock, but for internal use, I mean within the library the
> >pthread_mutex_lock
> >could be used with one more param, so that when pthread_mutex_lock is
called
> >from within the lib these
> >2 lines will never be executed.
> >
> >Any feedback would be appreciated.
> >Thanks a lot,
> >Viv
> >
> >
> >----- Original Message -----
> >From: "vc" <vcotirlea1@hotmail.com>
> >To: <pthreads-win32@sources.redhat.com>
> >Sent: Monday, February 23, 2004 6:45 PM
> >Subject: problem using pthread_cancel and pthread_mutex_lock
> >
> >
> >
> >
> >>Hi all,
> >>
> >>I am using the pthread library and I'm having a problem while using
> >>pthread_cancel and pthread_mutex_lock.
> >>Problem description:
> >>I start 2 threads: thread1 and thread2.
> >>thread1 is doing a pthread_mutex_lock(&mutex), then sleeps for 5 secs
and
> >>then it is doing
> >>a pthread_cancel for the thread2, then is doing a
> >>pthread_mutex_unlock(&mutex)
> >>Thread2 is doing a pthread_mutex_lock(&mutex), where it stays as the
mutex
> >>is owned
> >>by the thread1, and at this point the cancel is called.
> >>Even if in the cleanup procedure of the thread2 I'm doing an
> >>pthread_mutex_unlock or
> >>not, next time when the thread1 is trying a pthread_mutex_lock(&mutex)
it
> >>will block
> >>and never gets the mutex.
> >>Also the pthread_mutex_unlock(&mutex)  for the thread2 in the cleanup
> >>function fails
> >>(ret value is 1)
> >>
> >>So, my question is: how can a thread cleanly cancel another thread which
> >>
> >>
> >is
> >
> >
> >>waiting in a 'pthread_mutex_lock' call, so that this mutex is available
> >>again ?
> >>
> >>Here is a sample program:
> >>====================
> >>
> >>#include <windows.h>
> >>#include <stdio.h>
> >>#include <stdlib.h>
> >>#include <pthread.h>
> >>#include <errno.h>
> >>
> >>void cleanup_routine(void *arg);
> >>void reader_function(void *arg);
> >>void monitor(void *arg);
> >>int global_counter=0;
> >>
> >>pthread_mutex_t my_mutex;
> >>int id[2];
> >>pthread_t reader[2];
> >>int cancel_mode;
> >>
> >>
> >>int main(int argc, char *argv[])
> >>{
> >>   int my_args;
> >>   int err = 0;
> >>   cancel_mode = 1;
> >>
> >>   printf("We'll try to cancel with mode ASYNCHRONOUS\n");
> >>
> >>   id[0] = 1;
> >>   id[1] = 2;
> >>   pthread_mutex_init(&my_mutex, NULL);
> >>
> >>   my_args = 1;
> >>   pthread_create( &reader[0], NULL, (void*)&monitor, (void *)
&my_args);
> >>   Sleep(2000);
> >>   my_args = 2;
> >>   pthread_create( &reader[1], NULL, (void*)&reader_function, (void *)
> >>&my_args);
> >>
> >>   while(1) {
> >> Sleep(1000);
> >>   }
> >>}
> >>
> >>void monitor (void *arg )
> >>{
> >>   int retval;
> >>
> >>   printf("Monitor: Entering monitor routine\n\n");
> >>
> >>   printf("Monitor: monitor is locking thread...\n");
> >>   pthread_mutex_lock(&my_mutex);
> >>   printf("Monitor: monitor is locking thread - okay\n");
> >>   Sleep (5000);
> >>
> >>   printf("Monitor: monitor kills pthread 0x%x:\n", (unsigned int)
> >>reader[1]);
> >>   retval = pthread_cancel (reader[1]);
> >>   printf("Monitor: kill returns %d\n", retval);
> >>
> >>   printf("Monitor: monitor is unlocking thread...\n");
> >>   pthread_mutex_unlock(&my_mutex);
> >>   printf("Monitor: monitor is unlocking thread - okay\n");
> >>
> >>   printf("Monitor: monitor running\n");
> >>   Sleep (3000);
> >>   printf("Monitor: monitor is locking thread...\n");
> >>   pthread_mutex_lock(&my_mutex); // HERE: it will never get the lock!
It
> >>will hang here!
> >>   printf("Monitor: monitor is locking thread - okay\n");
> >>
> >>   Sleep(1000);
> >>   printf("Monitor: monitor is unlocking thread...\n");
> >>   pthread_mutex_unlock(&my_mutex);
> >>   printf("Monitor: monitor is unlocking thread - okay\n");
> >>}
> >>
> >>
> >>int args;
> >>
> >>void reader_function (void *arg )
> >>{
> >>   int i=0;
> >>   int id, state;
> >>   int retval;
> >>
> >>   pthread_cleanup_push(cleanup_routine, NULL);
> >>   retval = pthread_detach (pthread_self());
> >>
> >>   pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
> >>   printf("Thread: pthread_setcancelstate:   old state was %d\n",
state);
> >>
> >>   if (cancel_mode == 1) {
> >>       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
> >>   }
> >>
> >>   id = *(int *) arg;
> >>   printf("Thread: entered thread %d\n", id);
> >>   printf("Thread: thread returns: 0x%x\n", (unsigned int)
> >>
> >>
> >pthread_self());
> >
> >
> >>   printf("Thread: testthread is locking thread...\n");
> >>   pthread_mutex_lock(&my_mutex);
> >>   printf("Thread: testthread is locking thread - okay\n");
> >>
> >>   // HERE: it shouldn't come here as the thread will be canceled by the
> >>monitor thread
> >>   printf("Thread: testthread is unlocking thread...\n");
> >>   pthread_mutex_unlock(&my_mutex);
> >>   printf("Thread: testthread is unlocking thread - okay\n");
> >>
> >>   printf("Thread: reader_function finished\n");
> >>
> >>   pthread_cleanup_pop(0);
> >>}
> >>
> >>
> >>void cleanup_routine(void *arg)
> >>{
> >>   int ret = 0;
> >>   printf("ThreadCleanup: cleanup called\n");
> >>   Sleep(5000);
> >>
> >>   ret = pthread_mutex_unlock(&my_mutex);
> >>   printf("ThreadCleanup:Cleanup routine unlock ret = %d\n", ret);
> >>   printf("ThreadCleanup:waitThread_cleanup done\n");
> >>}
> >>
> >>
> >>The output looks like:
> >>=================
> >>We'll try to cancel with mode ASYNCHRONOUS
> >>Monitor: Entering monitor routine
> >>
> >>Monitor: monitor is locking thread...
> >>Monitor: monitor is locking thread - okay
> >>Thread: pthread_setcancelstate:   old state was 0
> >>Thread: entered thread 2
> >>Thread: thread returns: 0x312d80
> >>Thread: testthread is locking thread...
> >>Monitor: monitor kills pthread 0x312d80:
> >>Monitor: kill returns 0
> >>Monitor: monitor is unlocking thread...
> >>ThreadCleanup: cleanup called
> >>Monitor: monitor is unlocking thread - okay
> >>Monitor: monitor running
> >>Monitor: monitor is locking thread...
> >>ThreadCleanup:Cleanup routine unlock ret = 1
> >>ThreadCleanup:waitThread_cleanup done
> >>
> >>
> >>So, from the output can be seen that the 1st thread (called monitor)
will
> >>never be able
> >>to gain the mutex again.
> >>
> >>Sorry for the long post,
> >>Any help will be appreciated,
> >>Thanks a lot,
> >>Viv
> >>
> >>
> >>
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-03-01 16:27 ` vc
@ 2004-03-04 23:13   ` Ross Johnson
  2004-03-09 14:06     ` vc
  2004-03-09 14:15     ` Brano Kemen
  0 siblings, 2 replies; 12+ messages in thread
From: Ross Johnson @ 2004-03-04 23:13 UTC (permalink / raw)
  To: vc; +Cc: pthreads-win32

Hi VC,

I saw you're original post and the response that you got advising 
against async cancelation, etc, which I would urge you to consider 
further, even if you need to redesign your application.

There is another reason to avoid async cancelation that is specific to 
pthreads-win32: this implementation only approximates async cancelation 
because it relies on the thread actually running at some point after 
cancelation. So if your thread is blocked on a resource at the time that 
it's async canceled, it won't actually exit until it's unblocked in some 
way to resume execution (at which point it will exit immediately) - and 
if you can do that then you don't need async cancelation anyway. 
Unfortunately, the time you're most likely to really need an async 
cancel - to kill a thread blocked on a system resource that you can't 
unblock - is the very time it won't work in pthreads-win32, and if it 
did work, as in does in other implementations, then you'd probably be 
creating a resource leak. So it's hard to find a good argument for async 
cancel.

If you were to list the situations where your threads could possibly 
hang, then you'd probably find that there's a solution for each instance.

Re switching cancel state within the library:-
There are places in the library that temporarily suspend cancelability 
for cancel safety, usually because the standard requires it, but mutexes 
are not one of them, for the simple reason that, for the vast majority 
of cases, it isn't needed, while speed is, and for those rare cases that 
do need it, programmers can employ solutions similar to the one you've 
chosen.

A few more suggestions:
If you're using mutexes to control access to resources that could hang 
your application then maybe semaphores would be more appropriate - they 
are not owned by any thread and sem_wait() is a defined [deferred] 
cancelation point. There is also pthread_testcancel(), which you can use 
to create your own [deferred] cancelation points.

There are also timed versions of all of the synchronisation objects: 
pthread_mutex_timedlock(), sem_timedwait(), 
pthread_rwlock_timedrdlock(), pthread_rwlock_timedwrlock(), and 
pthread_cond_timedwait(); that you can perhaps exploit in your attempts 
to avoid canceling threads at all.

Hope that helps.

Regards.
Ross

vc wrote:

>Hi all,
>
>I found a solution to the problem I have described (see below my orig email)
>and I'm wondering if this is ok ...
>
>In my program I have to use asynchronous cancellation as I have something
>called a "thread monitor" and
>if one thread hangs I want after a while my thread monitor to kill it
>regardless of where that
>thread hanged. Using asynchronous cancellation makes problems (as I
>discovered until now)
>only when a thread is in a pthread_mutex_lock call, as in that case, by
>canceling the thread
>the mutex is in an unusable state.
>
>So what I have done is like this (see below): just before calling the
>pthread_mutex_lock
>I change the cancellation to deferred cancellation then call the
>pthread_mutex_lock and then set back
>the original cancellation mode:
>
>void reader_function (void *arg )
>{
>
> pthread_cleanup_push(cleanup_routine, (void *) &test_data);
>
> retval = pthread_detach (pthread_self());
>
> pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
> pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
>
> retval = protect_code_with_mutex_deferred();
> pthread_cleanup_pop(1);
>
> pthread_exit(NULL);
>}
>
>int protect_code_with_mutex_deferred(void)
>{
> int oldtype = 0;
>
> pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
> retval = pthread_mutex_lock(&my_mutex);
> pthread_setcanceltype(oldtype, NULL); //put back
> [...]
>}
>
>This seems to work just fine and seems to solve my problem. As I'm generaly
>using asynchronous cancellation
>my thread can be killed at any point and when a pthread_mutex_lock is done
>because I switch
>to deferred cancellation I can be sure that my thread will first go out from
>the pthread_mutex_lock
>call and then it will be canceled, so in my cleanup fction I can do an
>unlock of the mutex.
>
>But I am wondering why this way of solving the problem was not added to the
>pthread library? Am I missing something?
>Is something wrong here? Am I overseen something?
>
>If no, then in the pthread library in the pthread_mutex_lock at the
>beginning the:
> pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); could be called
>and at the end the:
> pthread_setcanceltype(oldtype, NULL);
>could be called.
>Of course some other changes are needed as pthread_setcanceltype calls also
>pthread_mutex_lock, but for internal use, I mean within the library the
>pthread_mutex_lock
>could be used with one more param, so that when pthread_mutex_lock is called
>from within the lib these
>2 lines will never be executed.
>
>Any feedback would be appreciated.
>Thanks a lot,
>Viv
>
>
>----- Original Message -----
>From: "vc" <vcotirlea1@hotmail.com>
>To: <pthreads-win32@sources.redhat.com>
>Sent: Monday, February 23, 2004 6:45 PM
>Subject: problem using pthread_cancel and pthread_mutex_lock
>
>
>  
>
>>Hi all,
>>
>>I am using the pthread library and I'm having a problem while using
>>pthread_cancel and pthread_mutex_lock.
>>Problem description:
>>I start 2 threads: thread1 and thread2.
>>thread1 is doing a pthread_mutex_lock(&mutex), then sleeps for 5 secs and
>>then it is doing
>>a pthread_cancel for the thread2, then is doing a
>>pthread_mutex_unlock(&mutex)
>>Thread2 is doing a pthread_mutex_lock(&mutex), where it stays as the mutex
>>is owned
>>by the thread1, and at this point the cancel is called.
>>Even if in the cleanup procedure of the thread2 I'm doing an
>>pthread_mutex_unlock or
>>not, next time when the thread1 is trying a pthread_mutex_lock(&mutex) it
>>will block
>>and never gets the mutex.
>>Also the pthread_mutex_unlock(&mutex)  for the thread2 in the cleanup
>>function fails
>>(ret value is 1)
>>
>>So, my question is: how can a thread cleanly cancel another thread which
>>    
>>
>is
>  
>
>>waiting in a 'pthread_mutex_lock' call, so that this mutex is available
>>again ?
>>
>>Here is a sample program:
>>====================
>>
>>#include <windows.h>
>>#include <stdio.h>
>>#include <stdlib.h>
>>#include <pthread.h>
>>#include <errno.h>
>>
>>void cleanup_routine(void *arg);
>>void reader_function(void *arg);
>>void monitor(void *arg);
>>int global_counter=0;
>>
>>pthread_mutex_t my_mutex;
>>int id[2];
>>pthread_t reader[2];
>>int cancel_mode;
>>
>>
>>int main(int argc, char *argv[])
>>{
>>   int my_args;
>>   int err = 0;
>>   cancel_mode = 1;
>>
>>   printf("We'll try to cancel with mode ASYNCHRONOUS\n");
>>
>>   id[0] = 1;
>>   id[1] = 2;
>>   pthread_mutex_init(&my_mutex, NULL);
>>
>>   my_args = 1;
>>   pthread_create( &reader[0], NULL, (void*)&monitor, (void *) &my_args);
>>   Sleep(2000);
>>   my_args = 2;
>>   pthread_create( &reader[1], NULL, (void*)&reader_function, (void *)
>>&my_args);
>>
>>   while(1) {
>> Sleep(1000);
>>   }
>>}
>>
>>void monitor (void *arg )
>>{
>>   int retval;
>>
>>   printf("Monitor: Entering monitor routine\n\n");
>>
>>   printf("Monitor: monitor is locking thread...\n");
>>   pthread_mutex_lock(&my_mutex);
>>   printf("Monitor: monitor is locking thread - okay\n");
>>   Sleep (5000);
>>
>>   printf("Monitor: monitor kills pthread 0x%x:\n", (unsigned int)
>>reader[1]);
>>   retval = pthread_cancel (reader[1]);
>>   printf("Monitor: kill returns %d\n", retval);
>>
>>   printf("Monitor: monitor is unlocking thread...\n");
>>   pthread_mutex_unlock(&my_mutex);
>>   printf("Monitor: monitor is unlocking thread - okay\n");
>>
>>   printf("Monitor: monitor running\n");
>>   Sleep (3000);
>>   printf("Monitor: monitor is locking thread...\n");
>>   pthread_mutex_lock(&my_mutex); // HERE: it will never get the lock! It
>>will hang here!
>>   printf("Monitor: monitor is locking thread - okay\n");
>>
>>   Sleep(1000);
>>   printf("Monitor: monitor is unlocking thread...\n");
>>   pthread_mutex_unlock(&my_mutex);
>>   printf("Monitor: monitor is unlocking thread - okay\n");
>>}
>>
>>
>>int args;
>>
>>void reader_function (void *arg )
>>{
>>   int i=0;
>>   int id, state;
>>   int retval;
>>
>>   pthread_cleanup_push(cleanup_routine, NULL);
>>   retval = pthread_detach (pthread_self());
>>
>>   pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
>>   printf("Thread: pthread_setcancelstate:   old state was %d\n", state);
>>
>>   if (cancel_mode == 1) {
>>       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
>>   }
>>
>>   id = *(int *) arg;
>>   printf("Thread: entered thread %d\n", id);
>>   printf("Thread: thread returns: 0x%x\n", (unsigned int)
>>    
>>
>pthread_self());
>  
>
>>   printf("Thread: testthread is locking thread...\n");
>>   pthread_mutex_lock(&my_mutex);
>>   printf("Thread: testthread is locking thread - okay\n");
>>
>>   // HERE: it shouldn't come here as the thread will be canceled by the
>>monitor thread
>>   printf("Thread: testthread is unlocking thread...\n");
>>   pthread_mutex_unlock(&my_mutex);
>>   printf("Thread: testthread is unlocking thread - okay\n");
>>
>>   printf("Thread: reader_function finished\n");
>>
>>   pthread_cleanup_pop(0);
>>}
>>
>>
>>void cleanup_routine(void *arg)
>>{
>>   int ret = 0;
>>   printf("ThreadCleanup: cleanup called\n");
>>   Sleep(5000);
>>
>>   ret = pthread_mutex_unlock(&my_mutex);
>>   printf("ThreadCleanup:Cleanup routine unlock ret = %d\n", ret);
>>   printf("ThreadCleanup:waitThread_cleanup done\n");
>>}
>>
>>
>>The output looks like:
>>=================
>>We'll try to cancel with mode ASYNCHRONOUS
>>Monitor: Entering monitor routine
>>
>>Monitor: monitor is locking thread...
>>Monitor: monitor is locking thread - okay
>>Thread: pthread_setcancelstate:   old state was 0
>>Thread: entered thread 2
>>Thread: thread returns: 0x312d80
>>Thread: testthread is locking thread...
>>Monitor: monitor kills pthread 0x312d80:
>>Monitor: kill returns 0
>>Monitor: monitor is unlocking thread...
>>ThreadCleanup: cleanup called
>>Monitor: monitor is unlocking thread - okay
>>Monitor: monitor running
>>Monitor: monitor is locking thread...
>>ThreadCleanup:Cleanup routine unlock ret = 1
>>ThreadCleanup:waitThread_cleanup done
>>
>>
>>So, from the output can be seen that the 1st thread (called monitor) will
>>never be able
>>to gain the mutex again.
>>
>>Sorry for the long post,
>>Any help will be appreciated,
>>Thanks a lot,
>>Viv
>>
>>    
>>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-02-23 17:43 vc
@ 2004-03-01 16:27 ` vc
  2004-03-04 23:13   ` Ross Johnson
  0 siblings, 1 reply; 12+ messages in thread
From: vc @ 2004-03-01 16:27 UTC (permalink / raw)
  To: pthreads-win32

Hi all,

I found a solution to the problem I have described (see below my orig email)
and I'm wondering if this is ok ...

In my program I have to use asynchronous cancellation as I have something
called a "thread monitor" and
if one thread hangs I want after a while my thread monitor to kill it
regardless of where that
thread hanged. Using asynchronous cancellation makes problems (as I
discovered until now)
only when a thread is in a pthread_mutex_lock call, as in that case, by
canceling the thread
the mutex is in an unusable state.

So what I have done is like this (see below): just before calling the
pthread_mutex_lock
I change the cancellation to deferred cancellation then call the
pthread_mutex_lock and then set back
the original cancellation mode:

void reader_function (void *arg )
{

 pthread_cleanup_push(cleanup_routine, (void *) &test_data);

 retval = pthread_detach (pthread_self());

 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);

 retval = protect_code_with_mutex_deferred();
 pthread_cleanup_pop(1);

 pthread_exit(NULL);
}

int protect_code_with_mutex_deferred(void)
{
 int oldtype = 0;

 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
 retval = pthread_mutex_lock(&my_mutex);
 pthread_setcanceltype(oldtype, NULL); //put back
 [...]
}

This seems to work just fine and seems to solve my problem. As I'm generaly
using asynchronous cancellation
my thread can be killed at any point and when a pthread_mutex_lock is done
because I switch
to deferred cancellation I can be sure that my thread will first go out from
the pthread_mutex_lock
call and then it will be canceled, so in my cleanup fction I can do an
unlock of the mutex.

But I am wondering why this way of solving the problem was not added to the
pthread library? Am I missing something?
Is something wrong here? Am I overseen something?

If no, then in the pthread library in the pthread_mutex_lock at the
beginning the:
 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); could be called
and at the end the:
 pthread_setcanceltype(oldtype, NULL);
could be called.
Of course some other changes are needed as pthread_setcanceltype calls also
pthread_mutex_lock, but for internal use, I mean within the library the
pthread_mutex_lock
could be used with one more param, so that when pthread_mutex_lock is called
from within the lib these
2 lines will never be executed.

Any feedback would be appreciated.
Thanks a lot,
Viv


----- Original Message -----
From: "vc" <vcotirlea1@hotmail.com>
To: <pthreads-win32@sources.redhat.com>
Sent: Monday, February 23, 2004 6:45 PM
Subject: problem using pthread_cancel and pthread_mutex_lock


> Hi all,
>
> I am using the pthread library and I'm having a problem while using
> pthread_cancel and pthread_mutex_lock.
> Problem description:
> I start 2 threads: thread1 and thread2.
> thread1 is doing a pthread_mutex_lock(&mutex), then sleeps for 5 secs and
> then it is doing
> a pthread_cancel for the thread2, then is doing a
> pthread_mutex_unlock(&mutex)
> Thread2 is doing a pthread_mutex_lock(&mutex), where it stays as the mutex
> is owned
> by the thread1, and at this point the cancel is called.
> Even if in the cleanup procedure of the thread2 I'm doing an
> pthread_mutex_unlock or
> not, next time when the thread1 is trying a pthread_mutex_lock(&mutex) it
> will block
> and never gets the mutex.
> Also the pthread_mutex_unlock(&mutex)  for the thread2 in the cleanup
> function fails
> (ret value is 1)
>
> So, my question is: how can a thread cleanly cancel another thread which
is
> waiting in a 'pthread_mutex_lock' call, so that this mutex is available
> again ?
>
> Here is a sample program:
> ====================
>
> #include <windows.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <pthread.h>
> #include <errno.h>
>
> void cleanup_routine(void *arg);
> void reader_function(void *arg);
> void monitor(void *arg);
> int global_counter=0;
>
> pthread_mutex_t my_mutex;
> int id[2];
> pthread_t reader[2];
> int cancel_mode;
>
>
> int main(int argc, char *argv[])
> {
>    int my_args;
>    int err = 0;
>    cancel_mode = 1;
>
>    printf("We'll try to cancel with mode ASYNCHRONOUS\n");
>
>    id[0] = 1;
>    id[1] = 2;
>    pthread_mutex_init(&my_mutex, NULL);
>
>    my_args = 1;
>    pthread_create( &reader[0], NULL, (void*)&monitor, (void *) &my_args);
>    Sleep(2000);
>    my_args = 2;
>    pthread_create( &reader[1], NULL, (void*)&reader_function, (void *)
> &my_args);
>
>    while(1) {
>  Sleep(1000);
>    }
> }
>
> void monitor (void *arg )
> {
>    int retval;
>
>    printf("Monitor: Entering monitor routine\n\n");
>
>    printf("Monitor: monitor is locking thread...\n");
>    pthread_mutex_lock(&my_mutex);
>    printf("Monitor: monitor is locking thread - okay\n");
>    Sleep (5000);
>
>    printf("Monitor: monitor kills pthread 0x%x:\n", (unsigned int)
> reader[1]);
>    retval = pthread_cancel (reader[1]);
>    printf("Monitor: kill returns %d\n", retval);
>
>    printf("Monitor: monitor is unlocking thread...\n");
>    pthread_mutex_unlock(&my_mutex);
>    printf("Monitor: monitor is unlocking thread - okay\n");
>
>    printf("Monitor: monitor running\n");
>    Sleep (3000);
>    printf("Monitor: monitor is locking thread...\n");
>    pthread_mutex_lock(&my_mutex); // HERE: it will never get the lock! It
> will hang here!
>    printf("Monitor: monitor is locking thread - okay\n");
>
>    Sleep(1000);
>    printf("Monitor: monitor is unlocking thread...\n");
>    pthread_mutex_unlock(&my_mutex);
>    printf("Monitor: monitor is unlocking thread - okay\n");
> }
>
>
> int args;
>
> void reader_function (void *arg )
> {
>    int i=0;
>    int id, state;
>    int retval;
>
>    pthread_cleanup_push(cleanup_routine, NULL);
>    retval = pthread_detach (pthread_self());
>
>    pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
>    printf("Thread: pthread_setcancelstate:   old state was %d\n", state);
>
>    if (cancel_mode == 1) {
>        pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
>    }
>
>    id = *(int *) arg;
>    printf("Thread: entered thread %d\n", id);
>    printf("Thread: thread returns: 0x%x\n", (unsigned int)
pthread_self());
>
>    printf("Thread: testthread is locking thread...\n");
>    pthread_mutex_lock(&my_mutex);
>    printf("Thread: testthread is locking thread - okay\n");
>
>    // HERE: it shouldn't come here as the thread will be canceled by the
> monitor thread
>    printf("Thread: testthread is unlocking thread...\n");
>    pthread_mutex_unlock(&my_mutex);
>    printf("Thread: testthread is unlocking thread - okay\n");
>
>    printf("Thread: reader_function finished\n");
>
>    pthread_cleanup_pop(0);
> }
>
>
> void cleanup_routine(void *arg)
> {
>    int ret = 0;
>    printf("ThreadCleanup: cleanup called\n");
>    Sleep(5000);
>
>    ret = pthread_mutex_unlock(&my_mutex);
>    printf("ThreadCleanup:Cleanup routine unlock ret = %d\n", ret);
>    printf("ThreadCleanup:waitThread_cleanup done\n");
> }
>
>
> The output looks like:
> =================
> We'll try to cancel with mode ASYNCHRONOUS
> Monitor: Entering monitor routine
>
> Monitor: monitor is locking thread...
> Monitor: monitor is locking thread - okay
> Thread: pthread_setcancelstate:   old state was 0
> Thread: entered thread 2
> Thread: thread returns: 0x312d80
> Thread: testthread is locking thread...
> Monitor: monitor kills pthread 0x312d80:
> Monitor: kill returns 0
> Monitor: monitor is unlocking thread...
> ThreadCleanup: cleanup called
> Monitor: monitor is unlocking thread - okay
> Monitor: monitor running
> Monitor: monitor is locking thread...
> ThreadCleanup:Cleanup routine unlock ret = 1
> ThreadCleanup:waitThread_cleanup done
>
>
> So, from the output can be seen that the 1st thread (called monitor) will
> never be able
> to gain the mutex again.
>
> Sorry for the long post,
> Any help will be appreciated,
> Thanks a lot,
> Viv
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: problem using pthread_cancel and pthread_mutex_lock
  2004-02-24  4:23 Simon Gerblich
@ 2004-02-26 15:59 ` vc
  0 siblings, 0 replies; 12+ messages in thread
From: vc @ 2004-02-26 15:59 UTC (permalink / raw)
  To: Simon Gerblich; +Cc: pthreads-win32

Thanks to all of you for your answers.
Viv

----- Original Message -----
From: "Simon Gerblich" <sgerblich@daronmont.com.au>
To: "vc" <vcotirlea1@hotmail.com>
Cc: <pthreads-win32@sources.redhat.com>
Sent: Tuesday, February 24, 2004 5:23 AM
Subject: RE: problem using pthread_cancel and pthread_mutex_lock


> Hi Viv,
>
> >So, my question is: how can a thread cleanly cancel another thread
> >which is waiting in a 'pthread_mutex_lock' call, so that this mutex is
> >available again ?
> I can see a few problems in what you are doing.
>
> A mutex is not really designed to be locked in a thread for a long time
and
> unlocked by another thread.  When I use a mutex in a thread I lock it - do
> what I have to do  - and then unlock it ASAP.  I don't use mutexes to
> synchronise threads.  I use them to protect data.  Pthread mutexes are not
> cancellation points.
>
> I use deferred cancellation instead of asynchronous cancellation because
of
> recommendations in "Programming with POSIX Threads" by David Butenhof.
> Page 150 "Avoid asynchronous cancellation.  It is difficult to use
correctly
> and is rarely useful."
> Page 151 "Asynchronous cancellation can occur at any hardware instruction.
> On some computers it may even be possible to interrupt some instructions
in
> the middle.  That makes it really difficult to determine what the canceled
> thread was doing."
> Page 151 "Call no code with asynchronous cancellation enabled unless you
> wrote it to be async-cancel safe - and even then, think twice!"
>
> I write my applications with deferred cancellation and the threads
blocking
> on message queues, which are cancellation points.  When a cancel is
> requested the threads exit cleanly when they next go to read the message
> queue.  I have minimal cancellation points in my code so that I know
exactly
> where my threads will cancel.
>
> Without knowing exactly what you are trying to do I think you should have
a
> look at using a condition variable instead of a mutex for your thread
> syncing.  Waiting on a condition variable is a cancellation point.
>
> Be aware that the Sleep() function on windows is not a cancellation point.
> I have written my own sleep functions to use with pthreads-win32 that
waits
> on condition variables with timeouts.
>
> If your not lurking in the google groups comp.programming.threads I'd
> recommend it.  I've learnt a lot following threads on pthreads, etc.
>
> Cheers,
> Simon
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: problem using pthread_cancel and pthread_mutex_lock
@ 2004-02-24  4:23 Simon Gerblich
  2004-02-26 15:59 ` vc
  0 siblings, 1 reply; 12+ messages in thread
From: Simon Gerblich @ 2004-02-24  4:23 UTC (permalink / raw)
  To: vc; +Cc: pthreads-win32

Hi Viv,

>So, my question is: how can a thread cleanly cancel another thread
>which is waiting in a 'pthread_mutex_lock' call, so that this mutex is
>available again ?
I can see a few problems in what you are doing.

A mutex is not really designed to be locked in a thread for a long time and
unlocked by another thread.  When I use a mutex in a thread I lock it - do
what I have to do  - and then unlock it ASAP.  I don't use mutexes to
synchronise threads.  I use them to protect data.  Pthread mutexes are not
cancellation points.

I use deferred cancellation instead of asynchronous cancellation because of
recommendations in "Programming with POSIX Threads" by David Butenhof.
Page 150 "Avoid asynchronous cancellation.  It is difficult to use correctly
and is rarely useful."
Page 151 "Asynchronous cancellation can occur at any hardware instruction.
On some computers it may even be possible to interrupt some instructions in
the middle.  That makes it really difficult to determine what the canceled
thread was doing."
Page 151 "Call no code with asynchronous cancellation enabled unless you
wrote it to be async-cancel safe - and even then, think twice!"

I write my applications with deferred cancellation and the threads blocking
on message queues, which are cancellation points.  When a cancel is
requested the threads exit cleanly when they next go to read the message
queue.  I have minimal cancellation points in my code so that I know exactly
where my threads will cancel.  

Without knowing exactly what you are trying to do I think you should have a
look at using a condition variable instead of a mutex for your thread
syncing.  Waiting on a condition variable is a cancellation point.

Be aware that the Sleep() function on windows is not a cancellation point.
I have written my own sleep functions to use with pthreads-win32 that waits
on condition variables with timeouts.

If your not lurking in the google groups comp.programming.threads I'd
recommend it.  I've learnt a lot following threads on pthreads, etc.

Cheers,
Simon

^ permalink raw reply	[flat|nested] 12+ messages in thread

* problem using pthread_cancel and pthread_mutex_lock
@ 2004-02-23 17:43 vc
  2004-03-01 16:27 ` vc
  0 siblings, 1 reply; 12+ messages in thread
From: vc @ 2004-02-23 17:43 UTC (permalink / raw)
  To: pthreads-win32

Hi all,

I am using the pthread library and I'm having a problem while using
pthread_cancel and pthread_mutex_lock.
Problem description:
I start 2 threads: thread1 and thread2.
thread1 is doing a pthread_mutex_lock(&mutex), then sleeps for 5 secs and
then it is doing
a pthread_cancel for the thread2, then is doing a
pthread_mutex_unlock(&mutex)
Thread2 is doing a pthread_mutex_lock(&mutex), where it stays as the mutex
is owned
by the thread1, and at this point the cancel is called.
Even if in the cleanup procedure of the thread2 I'm doing an
pthread_mutex_unlock or
not, next time when the thread1 is trying a pthread_mutex_lock(&mutex) it
will block
and never gets the mutex.
Also the pthread_mutex_unlock(&mutex)  for the thread2 in the cleanup
function fails
(ret value is 1)

So, my question is: how can a thread cleanly cancel another thread which is
waiting in a 'pthread_mutex_lock' call, so that this mutex is available
again ?

Here is a sample program:
====================

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>

void cleanup_routine(void *arg);
void reader_function(void *arg);
void monitor(void *arg);
int global_counter=0;

pthread_mutex_t my_mutex;
int id[2];
pthread_t reader[2];
int cancel_mode;


int main(int argc, char *argv[])
{
   int my_args;
   int err = 0;
   cancel_mode = 1;

   printf("We'll try to cancel with mode ASYNCHRONOUS\n");

   id[0] = 1;
   id[1] = 2;
   pthread_mutex_init(&my_mutex, NULL);

   my_args = 1;
   pthread_create( &reader[0], NULL, (void*)&monitor, (void *) &my_args);
   Sleep(2000);
   my_args = 2;
   pthread_create( &reader[1], NULL, (void*)&reader_function, (void *)
&my_args);

   while(1) {
 Sleep(1000);
   }
}

void monitor (void *arg )
{
   int retval;

   printf("Monitor: Entering monitor routine\n\n");

   printf("Monitor: monitor is locking thread...\n");
   pthread_mutex_lock(&my_mutex);
   printf("Monitor: monitor is locking thread - okay\n");
   Sleep (5000);

   printf("Monitor: monitor kills pthread 0x%x:\n", (unsigned int)
reader[1]);
   retval = pthread_cancel (reader[1]);
   printf("Monitor: kill returns %d\n", retval);

   printf("Monitor: monitor is unlocking thread...\n");
   pthread_mutex_unlock(&my_mutex);
   printf("Monitor: monitor is unlocking thread - okay\n");

   printf("Monitor: monitor running\n");
   Sleep (3000);
   printf("Monitor: monitor is locking thread...\n");
   pthread_mutex_lock(&my_mutex); // HERE: it will never get the lock! It
will hang here!
   printf("Monitor: monitor is locking thread - okay\n");

   Sleep(1000);
   printf("Monitor: monitor is unlocking thread...\n");
   pthread_mutex_unlock(&my_mutex);
   printf("Monitor: monitor is unlocking thread - okay\n");
}


int args;

void reader_function (void *arg )
{
   int i=0;
   int id, state;
   int retval;

   pthread_cleanup_push(cleanup_routine, NULL);
   retval = pthread_detach (pthread_self());

   pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &state);
   printf("Thread: pthread_setcancelstate:   old state was %d\n", state);

   if (cancel_mode == 1) {
       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &state);
   }

   id = *(int *) arg;
   printf("Thread: entered thread %d\n", id);
   printf("Thread: thread returns: 0x%x\n", (unsigned int) pthread_self());

   printf("Thread: testthread is locking thread...\n");
   pthread_mutex_lock(&my_mutex);
   printf("Thread: testthread is locking thread - okay\n");

   // HERE: it shouldn't come here as the thread will be canceled by the
monitor thread
   printf("Thread: testthread is unlocking thread...\n");
   pthread_mutex_unlock(&my_mutex);
   printf("Thread: testthread is unlocking thread - okay\n");

   printf("Thread: reader_function finished\n");

   pthread_cleanup_pop(0);
}


void cleanup_routine(void *arg)
{
   int ret = 0;
   printf("ThreadCleanup: cleanup called\n");
   Sleep(5000);

   ret = pthread_mutex_unlock(&my_mutex);
   printf("ThreadCleanup:Cleanup routine unlock ret = %d\n", ret);
   printf("ThreadCleanup:waitThread_cleanup done\n");
}


The output looks like:
=================
We'll try to cancel with mode ASYNCHRONOUS
Monitor: Entering monitor routine

Monitor: monitor is locking thread...
Monitor: monitor is locking thread - okay
Thread: pthread_setcancelstate:   old state was 0
Thread: entered thread 2
Thread: thread returns: 0x312d80
Thread: testthread is locking thread...
Monitor: monitor kills pthread 0x312d80:
Monitor: kill returns 0
Monitor: monitor is unlocking thread...
ThreadCleanup: cleanup called
Monitor: monitor is unlocking thread - okay
Monitor: monitor running
Monitor: monitor is locking thread...
ThreadCleanup:Cleanup routine unlock ret = 1
ThreadCleanup:waitThread_cleanup done


So, from the output can be seen that the 1st thread (called monitor) will
never be able
to gain the mutex again.

Sorry for the long post,
Any help will be appreciated,
Thanks a lot,
Viv

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2004-03-10 11:11 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-09 23:25 problem using pthread_cancel and pthread_mutex_lock Simon Gerblich
2004-03-10  0:57 ` Will Bryant
2004-03-10 11:11 ` vc
  -- strict thread matches above, loose matches on Subject: below --
2004-02-24  4:23 Simon Gerblich
2004-02-26 15:59 ` vc
2004-02-23 17:43 vc
2004-03-01 16:27 ` vc
2004-03-04 23:13   ` Ross Johnson
2004-03-09 14:06     ` vc
2004-03-09 14:15     ` Brano Kemen
2004-03-09 15:09       ` Panagiotis E. Hadjidoukas
2004-03-09 15:42         ` Brano Kemen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).