This is the mail archive of the
mailing list for the GCC project.
Re: [3.3] Followup to C++ forced unwinding
- From: Mark Mitchell <mark at codesourcery dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: Richard Henderson <rth at redhat dot com>, gcc-patches at gcc dot gnu dot org, ncm at cantrip dot org, drepper at redhat dot com
- Date: 30 Apr 2003 17:29:20 -0700
- Subject: Re: [3.3] Followup to C++ forced unwinding
- Organization: CodeSourcery, LLC
- References: <20030430175335.GA18958@twiddle.net> <email@example.com> <20030430210342.GB697@redhat.com> <firstname.lastname@example.org> <email@example.com>
(I've replying to both Jason and Ulrich in this message.)
> To me, the (a) condition is much more like the (c) condition. That was
> also the consensus at the ABI committee meetings. I don't remember anyone
> disagreeing that cancellation and longjmp_unwind would use the same code.
Heck, I don't even remember this being discussed, so you're way ahead of
> For cancellation and longjmp_unwind, we would like to be able to support
> the first use, but we cannot support the second. There is no good answer
> to this question, which is why it's fudged in the ABI; basically, the ABI
> says that if a compiler is clever enough to distinguish the cases, it can,
> but it's not required.
> No, this is not acceptable. Once cancelled a thread cannot be allowed
> to prevent this. Cancellation changes the internal state of the thread,
> it cannot continue running. The POSIX standard is clear on that, if a
> thread leaves the cleanup handler in some way the behavior is undefined.
> The rethrow is mandatory in case the catch blocks are expected to run.
> There is no discussion possible, this is a fact.
This whole idea -- that we unwind the stack running code when a thread
is cancelled -- is outside POSIX.
And all "undefined behavior" means is that we can choose what it does,
and that users cannot rely on that behavior being portable to other
> The simple solution is to give up on handling catch(...) at all in forced
> unwind situations and tell people that they should use a local object
> cleanup instead.
If it is really true that we cannot enter "catch(...)" blocks for some
reason (which I do not yet believe, despite Ulrich's usual inimitable
expression of confidence), then running into a "catch(...)" block while
unwinding should result in a call to std::terminate.
Unwinding past a "catch (...)" clause without running it is not helpful
to people. It's fine to tell people to use destructors, but we're
silently changing the meaning of tons of existing code, all of which
will now have to be audited for safety.
In practice, this is the kind of thing that causes people not to use
C++. A life-critical system can restart itself if an abort occurs --
they're designed for that -- but silently skipping a cleanup can kill
people. I'd have to advise customers never to use deferred thread
cancellation with C++ libraries, without doing an audit of every
catch(...) clause in the library.
> > If the catch-clause chooses not to rethrow the exception, that just
> > means this thread isn't going to be cancelled, which could happen from
> > an ordinary pthread cancellation handler.
> It could, but that would be a bug in the program. A cancellation request,
> when acted on, is defined to be equivalent to pthread_exit, and there is
> nothing to suggest that pthread_exit sometimes doesn't actually terminate
> the thread.
I'm not sure why this would be a bug -- it's not even undefined
behavior. But, if it is a bug, then a "catch(...)" that doesn't rethrow
would be the same bug. There's no harm in providing the user a
C++-specific way to make the same mistake.
There's nothing that says that a destructor must return, or cannot
contain arbitrary code. The distinction that's being made between
"catch (...)" clauses and destructors is entirely artificial.
Mark Mitchell <firstname.lastname@example.org>