This is the mail archive of the
mailing list for the GCC project.
Re: [3.3] Followup to C++ forced unwinding
On Wed, 2003-04-30 at 22:34, Ulrich Drepper wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> Mark Mitchell wrote:
> > Maybe you could point me at the source code for one of these thread
> > library implementations where (1) holds, but (2) does not?
> Just look at the code.
> Cancellation is idempotent. Therefore a flag is set so that
> cancellation cannot happen in cancellation handlers. If the program
> continues cancellation won't be possible anymore and the program can get
> stuck. pthread_exit() doesn't work anymore is one other thing. In
> other implementation (maybe even in LinuxThreads) you get endless loops
> of calling cleanup handlers.
Cancellation doesn't occur again, even if you call a cancellation point.
You can't call pthread_exit.
A program calling pthread_join may wait arbitrarily long for the
cancelled thread to exit.
That's POSIX threads for you. It makes no difference whether or not
these things happen from within a pthread_cleanup_push function that
happens to run for a long time, a pthread_key_create destructor that
happens to run for a long time, or a catch handler that chooses not to
rethrow the exception.
If the catch handler chooses not to rethrow the exception, one of a few
things will happen:
(1) The process dies.
(2) The thread runs forever.
(3) The thread misbehaves by calling pthread_exit, or some other
function it's no longer allowed to call.
(4) At some point the thread will return from the main thread function.
Only (4) requires any special handling in the threads library, and the
special handling required is not complex: run pthread_key_create
destructors that have not yet been run, and terminate the thread.
It's perfectly reasonable to argue that catch-clauses should, by
default, rethrow. Likewise, it's reasonable to argue that "break"
should be the default after a case label, and that "extern void f()"
should mean "extern void f(void)" rather than "extern void f(...)".
C++ programmers understand that "catch (...)" should usually rethrow in
the same way that C programmers know that "break" should usually be
inserted before a case label. As with fall-through case-statements,
however, it is sometimes reasonable just to catch the exception.
The most useful things for pthread cancellation to do in C++ is to throw
an ordinary exception of some type "pthread_cancellation" with no
special semantics whatsoever.
The reason the current compromise is acceptable is that it provides a
forward-compatible subset of that functionality:
- You can't catch that particular exception type, but you can catch it
with catch (...). If the exception later gets the type
pthread_cancellation, then all of your catch (...) handlers will still
catch it, but you'll also be able to catch just thread-cancellation
- You can't choose not to rethrow the exception, nor can you choose to
rethrow an exception of a different type -- but in these circumstances
your process will die; therefore, when the more useful semantics are
provided all processes that did not die before will still not die.
This compromise will not do what C++ programmers want, and it will still
prevent them from using many exception-safe libraries in multi-threaded
programs, but some libraries may work, and at least the failure mode for
the others will be relatively obvious.
Mark Mitchell <firstname.lastname@example.org>