|
Home > Archive > Unix Programming > February 2005 > A problem with pthread_cancel
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
A problem with pthread_cancel
|
|
| Daniel Haude 2005-02-11, 6:03 pm |
| Hello,
I have the following routine that is executed as a thread:
void thread_func(void *args)
{
(void) args;
for(;;) {
pthread_mutex_lock(&mtx);
/* call some supposedly thread-safe library functions */
pthread_mutex_unlock(&mtx);
pthread_testcancel();
}
}
(This isn't the actual code because I'm retyping it from memory -- I don't
have net access on the other machine).
In the main thread of my program, after having started this thread, I stop
it like this:
pthread_cancel(my_thread);
pthread_join(my_thread);
The thread stops alright, but then my app freezes at the next call to
pthread_mutex_lock(). It seems that the cancellation request gets executed
immediately and not at the pthread_testcancel() call above, therefore the
mutex never gets unlocked.
Probably there are cancellation points somewhere inside the functions I'm
calling from my code, and to which I have no access. Can I do this cleanly
with pthread_cancel, or should I use some other signalling method, like
semaphores?
Thanks,
--Daniel
| |
| Paul Pluzhnikov 2005-02-11, 6:03 pm |
| Daniel Haude <haude@kir.physnet.uni-hamburg.de> writes:
> Probably there are cancellation points somewhere inside the functions I'm
> calling from my code, and to which I have no access.
That is the most likely answer.
> Can I do this cleanly with pthread_cancel
Yes: do "man pthread_cleanup_push".
Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
| |
| Måns Rullgård 2005-02-11, 6:03 pm |
| Paul Pluzhnikov <ppluzhnikov-nsp@charter.net> writes:
> Daniel Haude <haude@kir.physnet.uni-hamburg.de> writes:
>
>
> That is the most likely answer.
>
>
> Yes: do "man pthread_cleanup_push".
In my experience, using pthread_cancel() is rarely needed with careful
design.
--
Måns Rullgård
mru@inprovide.com
| |
| David Schwartz 2005-02-11, 6:03 pm |
|
"Måns Rullgård" <mru@inprovide.com> wrote in message
news:yw1xoeerccvl.fsf@ford.inprovide.com...
> In my experience, using pthread_cancel() is rarely needed with careful
> design.
And generally is much easier to avoid than to use properly.
DS
| |
| Måns Rullgård 2005-02-11, 6:03 pm |
| "David Schwartz" <davids@webmaster.com> writes:
> "Måns Rullgård" <mru@inprovide.com> wrote in message
> news:yw1xoeerccvl.fsf@ford.inprovide.com...
>
>
> And generally is much easier to avoid than to use properly.
True. In fact, I can't remember ever using it for anything serious.
--
Måns Rullgård
mru@inprovide.com
| |
| Daniel Haude 2005-02-21, 7:54 am |
| On Fri, 11 Feb 2005 20:29:16 +0100,
Måns Rullgård <mru@inprovide.com> wrote
in Msg. <yw1xk6pedhf7.fsf@ford.inprovide.com>
> "David Schwartz" <davids@webmaster.com> writes:
>
>
> True. In fact, I can't remember ever using it for anything serious.
>
So how /should/ inter-thread communication be set up? I'd now just
introduce a global flag variable which gets periodically checked by thread
A, which will terminate once thread B sets it.
A side note: Does the flag variable have to be protected with a mutex in
this case? I don't think so but you never know...
thanks for all the tips, guys.
--D.
| |
| Ian Pilcher 2005-02-21, 6:00 pm |
| Daniel Haude wrote:
> A side note: Does the flag variable have to be protected with a
mutex in
> this case? I don't think so but you never know...
It has to be protected with something. A mutex is probably the simplest
mechanism, but you also might want to use a read-write lock if you're
going to have a lot of threads checking the flag.
--
========================================
================================
Ian Pilcher i.pilcher@comcast.net
========================================
================================
| |
| David Schwartz 2005-02-22, 2:52 am |
|
"Daniel Haude" <haude@kir.physnet.uni-hamburg.de> wrote in message
news:slrnd1jq5t.9f5.haude@kir.physnet.uni-hamburg.de...
> So how /should/ inter-thread communication be set up? I'd now just
> introduce a global flag variable which gets periodically checked by thread
> A, which will terminate once thread B sets it.
Don't specifically think of it as inter-thread communication. Just think
of it as data structures that could be used by any thread that happens to
need it.
> A side note: Does the flag variable have to be protected with a mutex in
> this case? I don't think so but you never know...
What do you need the flag variable for? A thread should continue to run
so long as there is work for it to do and should terminate itself when there
is no more work. Don't think about terminating a thread, perhaps you are
asking how to cancel a job?
DS
| |
| Daniel Haude 2005-02-22, 8:49 pm |
| On Mon, 21 Feb 2005 09:22:02 -0600,
Ian Pilcher <i.pilcher@comcast.net> wrote
in Msg. <Ya-dnVwhKt4HYYTfRVn-qA@comcast.com>
> Daniel Haude wrote:
> mutex in
>
> It has to be protected with something. A mutex is probably the simplest
> mechanism, but you also might want to use a read-write lock if you're
> going to have a lot of threads checking the flag.
No, this is strictly a two-thread thing: Thread A creates thread B which
then runs a constant loop doing stuff until A tells it to stop, upon which
A does a pthread_join(). Shouldn't it be enough to have thread A set some
global variable which B occasionally checks -- without any protection?
I'm not trying to wriggle out of having to use a mutex. I'm merely asking
if there are pitfalls using this. Pure theory anyway: I AM using a mutex
and will continue to do so, just to be sure, but do I have to in this
case?
Thanks,
--Daniel
| |
| David Schwartz 2005-02-22, 8:49 pm |
|
"Daniel Haude" <haude@kir.physnet.uni-hamburg.de> wrote in message
news:slrnd1mkb9.1gc.haude@kir.physnet.uni-hamburg.de...
> No, this is strictly a two-thread thing: Thread A creates thread B which
> then runs a constant loop doing stuff until A tells it to stop, upon which
> A does a pthread_join(). Shouldn't it be enough to have thread A set some
> global variable which B occasionally checks -- without any protection?
No. Thread B may never see the change.
> I'm not trying to wriggle out of having to use a mutex. I'm merely asking
> if there are pitfalls using this. Pure theory anyway: I AM using a mutex
> and will continue to do so, just to be sure, but do I have to in this
> case?
According to the POSIX standard, you do. However, on all currently
existing implementations (that I know of), you do not if the code for thread
B is sufficiently complex.
DS
| |
| Daniel Haude 2005-02-23, 6:01 pm |
| On Tue, 22 Feb 2005 12:24:42 -0800,
David Schwartz <davids@webmaster.com> wrote
in Msg. <cvg4ea$q2q$1@nntp.webmaster.com>
>
> "Daniel Haude" <haude@kir.physnet.uni-hamburg.de> wrote in message
> news:slrnd1mkb9.1gc.haude@kir.physnet.uni-hamburg.de...
>
>
> No. Thread B may never see the change.
>
>
> According to the POSIX standard, you do. However, on all currently
> existing implementations (that I know of), you do not if the code for thread
> B is sufficiently complex.
Thanks for the explanations. So I gather that an implementation is not
required to make some change to a shared variable visible to anothar
thread, at any point in time, unless there is some mutex stuff going on.
I guess I should read up on POSIX.
Thanks again,
--D.
| |
| Måns Rullgård 2005-02-23, 6:01 pm |
| Daniel Haude <haude@kir.physnet.uni-hamburg.de> writes:
> On Tue, 22 Feb 2005 12:24:42 -0800,
> David Schwartz <davids@webmaster.com> wrote
> in Msg. <cvg4ea$q2q$1@nntp.webmaster.com>
>
> Thanks for the explanations. So I gather that an implementation is not
> required to make some change to a shared variable visible to anothar
> thread, at any point in time, unless there is some mutex stuff going on.
More specifically, a memory barrier of some kind.
--
Måns Rullgård
mru@inprovide.com
| |
| David Schwartz 2005-02-23, 6:01 pm |
|
"Daniel Haude" <haude@kir.physnet.uni-hamburg.de> wrote in message
news:slrnd1p9l6.109.haude@kir.physnet.uni-hamburg.de...
> Thanks for the explanations. So I gather that an implementation is not
> required to make some change to a shared variable visible to anothar
> thread, at any point in time, unless there is some mutex stuff going on.
>
> I guess I should read up on POSIX.
There are several different cases in which it is required to make a
change visible, however, if you don't fall into one of those cases, what
value you will see is undefined. It could be the value before the change, it
could be the value after the change, or it could be some mixture that makes
no sense at all.
The general consensus is that using a volatile integer as a 'yes/no'
flag without a lock is adequate provided:
1) The code that checks the flag is sufficiently complex. For example:
while(flag==0) i++;
is not acceptable.
2) There is no critical need to detect the flag in any particular time
frame. Eventual detection is adequate.
3) The implementation is tested on each platform with the understanding
that it relies on non-portable behavior.
4) Failure to detect the flag does not result in fatal behavior. Failure
to shutdown or failure to cleanly shutdown, for example, would be tolerable.
Failure to work at all would not be.
The reason this 'just works' is because compilers are smart, but not too
smart. They compiler might see that in:
while(flag==0) i++;
The value of 'flag' cannot be changed by 'i++' (unless this is c++ and
'i' is a reference!) so it may keep it in a register, making the other
thread's changes invisible forever. However, if the code is:
while(flag==0) myfunc();
The compiler (generally!) has no way to tell whether or not 'myfunc'
modifies 'flag' and so it will have to retest it from memory each time. So
long as you call at least one function that cannot be inlined, you should
see the changes eventually.
Any mechanism another thread could use to modify 'flag' could also be
used by a function in another compilation unit. So this "just works" on all
current implementations that I know of. Future behavior, of course, cannot
be guaranteed.
DS
| |
| David Schwartz 2005-02-23, 6:01 pm |
|
"Måns Rullgård" <mru@inprovide.com> wrote in message
news:yw1xy8df89xx.fsf@inprovide.com...
> More specifically, a memory barrier of some kind.
In general, memory barriers only solve the processor problem, not the
compiler problem or problems that might be introduced by other hardware.
Only a mutex (or one of the other officially blessed methods) is portable.
DS
|
|
|
|
|