This is the mail archive of the
mailing list for the pthreas-win32 project.
RE: asynchronous cancellation
- To: 'Jason Nye' <jnye at nbnet dot nb dot ca>, Ross Johnson <rpj at ise dot canberra dot edu dot au>
- Subject: RE: asynchronous cancellation
- From: "Bossom, John" <John dot Bossom at Cognos dot COM>
- Date: Tue, 16 Nov 1999 17:40:03 -0500
- Cc: 'Pthreads-win32' <pthreads-win32 at sourceware dot cygnus dot com>
No flames intended... (and there are none contained within this email
I'm not trying to say "ours is better than yours" either.
(Better grab a coffee... I got kind of long winded here!)
The situation I am trying to describe has nothing to do with the
pthreads-win32 implementation or your implementation, or any other
implementation for that matter.
It is a general comment I have that the C++ features
- automatic C++ object destructors
- C++ exception handling
are in direct conflict with the "philosophy" of the PThreads Cancellation
programming paradigm (specifically cleanup) regardless of
As a C++ programmer, I wouldn't use the pthreads cancellation mechanism
simply because it does prevent cleaning up resources held by automatic
(stack) based C++ objects (or, conversely, it prevents me from using these
C++ features). The cleanup code one would put in their C++ 'catch' would
have to be duplicated in their pthread_cleanup_push routines... so a C++
programmer might as well choose one methodology or the other:
a) pthread cancellation mechanism, with push/pop for cleanup:
- never using automatic objects that retain resources,
- never using/relying on the C++ catch code being executed
b) C++ features:
- automatic C++ object destructors
- C++ Exception Handling
- your own method of cancelling a thread
and unwind the stack by throwing an exception)
Attempting to mix the two such that you have no resource leaks wouldn't be
There is no standard that specifies the behaviour between C++ and PThreads.
As a result, the behaviour of a PThreads library and these C++ features is
implementation specific and should not be relied upon.
My point is, you cannot rely on the two mechanisms working together from
machine to machine as there is no standard enforcing this.
As you have stated, your implementation bypasses stack-unwinding... there
is nothing wrong with this... as far as I know, the native PThreads
on all UNIX platforms also bypass C++ stack unwinding - this is their
behaviour - PThreads knows nothing about C++.
I am not touting the pthreads-win32 mechanism either... I personally
the pthreads cancellation mechanism on any platform (including
if I was writing code in C++ because it limits/prevents the use of these C++
Most PThreads books I have read state that you should avoid using
the PThreads cancellation mechanism since it can result in complex code
and bypasses all C++ stack unwinding resulting in lost resources (see my
little C++ example below. These books typically recommend that C++
implement their own cancellation mechanism (i.e. setting a variable and
checking it periodically within the thread, or by some other means - then
throw a C++
exception out to the thread's main routine, and exit the thread there by
returning from the main routine.) This is the philosophy taken by Threads++
by RogueWave(?). The programmer defines cancellation points within their
code. The cancelation check simply returns whether you should carry on or
cancel. It is up to the programmer to then shutdown the thread however they
choose. This model works for
both C and C++ without having to sacrifice language features.
i.e.) C++ guarantees that objects declared on the stack have their
destructors invoked no matter how you leave the scope in which they
are defined. There are two valid methods of leaving the scope, as
far as C++ is concerned:
1) simply executing to the end of the scope in which the
2) jumping out of the scope through the use of the C++
In both cases, the C++ compiler places sufficient implicit hooks
the generated code to ensure that your automatic destructors for
stack based objects are called.
The programming paradigm for the PThreads cancellation mechanism is that
only those destructors explicitly registered with pthread_cleanup_push are
called; then the thread exists in place (i.e. doesn't return through the
call stack)... this step bypasses the cleanup of all stack based C++ objects
... any resources being held by these objects are forever lost).
Here is an example snippet of code (sorry if it isn't accurate
C++, but you'll get the idea...
// compiler generated implicit code to call
// classInstance.~MyClass() here...
By stack unwinding I mean that, whether or not you use C++ exception
handling, when you leave the scope in which an automatic (i.e. stack
based variable) is created, the destructors are implicitly called
(i.e. the C++ compiler generates an implicit call to
in the above example).
Now, if someRoutine was called within a thread, and we are currently running
in doSomeStuff() when the cancellation is recognised, the object
would not have it's destructor called and any resources held by it will be
A C++ programmer wishing to use the pthread cancellation mechanism must take
special care in order to get these features to work together... They must
only use deferred cancellation and only enable it in safe situations, or
re-write the above to look something like
MyClass * classInstance = New MyClass();
pthread_cleanup_push( classInstance, MyClass::~MyClass );
pthread_cleanup_pop( classInstance, 1 );
I hope I have clarified myself and I do thank you for showing me how to
implement an asynchronous cancel by basically telling the CPU to start
executing code at a specific address...
From: Jason Nye [mailto:email@example.com]
Sent: Tuesday, November 16, 1999 3:57 PM
To: Ross Johnson
Subject: Re: asynchronous cancellation
John Bossom wrote:
> > Interesting solution...
> > To work with the pthreads-win32 library, your AsyncCancelPoint
> > needs to get pSelf from dynamically declared TLS... (i.e. pthread_self,
> > or it's internal implementation).
> > Just a note to C++ users: one shouldn't use the built-in pthreads
> > cancellation if they expect C++ stack unwinding to work....
I'm a C++ developer, not necessarily a guru in the ways of pthreads -- I
do know some its specifications, however -- please, no flames!
Why does the stack have to be unwound when a thread is cancelled? Is
this a requirement of pthreads (I'm pretty sure this is not the case) or
is it just the way that pthreads-win32 has always implemented it and you
are sticking to this design? My ObjectThread library does not unwind the
stack when a thread is cancelled and the net result is that it has no
weird implementation-specific side effects from using exception handling
(whether SEH or C++) and there is no unnecessary performance overhead
when a thread gets cancelled -- no unwinding the stack, just executing
cleanup handlers/destructors and calling _exitthreadex().
IMHO using SEH and C++ exceptions ties pthreads-win32 to specific
compilers/languages and introduces unnecessary implementation-specific
side-effects that will catch some developers by surprise (it caught me
by surprise -- and note John's last point). Cancellation can be easily
implemented without using such constructs and the result is a
compiler-independent library in which cancellation acts as one would
Note that I'm not trying to say "Mine is better than yours", I'm just
saying that there is an another way to achieve cancellation that may be
more reliable and more compliant to the standard.