This is the mail archive of the
mailing list for the GCC project.
Re: [3.3] Followup to C++ forced unwinding
Mark Mitchell said:
> The only reason std::terminate came into this discussion at all was that
> it appeared impossible to get Ulrich to implement The Right Thing. In
> particular there were two classes of programs, and everyone agreed on
> the behavior for one class. For the other class, we did not all agree.
> I suggested we call terminate for programs in that second class because
> it is better to call terminate that to silently do The Wrong Thing,
> which was the only other proposal on the table.
OK... I've been doing further reading/research on the thread topic. Let's
take individual postings I find of interest one at a time:
>>>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. Deferred cancellation
>>>semantics don't give you any guarantees about when a thread will exit
>>>after it has been cancelled.
>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.
First, I have to say that I don't have a copy of the actual standard. I'm
using the publications of the Open Group as reference:
http://www.opengroup.org/. I can't find any reference indicating that a
thread cannot continue running once cancelled. In fact, it appears to be
exactly the opposite, since a cleanup handler is allowed to call nearly
anything (see the next point).
http://www.opengroup.org/onlinepubs/007904975/ indicates that the only
thing you can't do within a cleanup handler without invoking undefined
behavior is to call setjump/longjump. Calls to pthread_exit, or anything
else for that matter, should be well defined. It further says:
"This volume of IEEE Std 1003.1-2001 currently leaves unspecified the
effect of calling longjmp() from a signal handler executing in a POSIX
System Interfaces function. If an implementation wants to allow this and
give the programmer reasonable behavior, the longjmp() function has to
call all cancellation cleanup handlers that have been pushed but not
popped since the time setjmp() was called."
So an implementation CAN allow this, though it would still be undefined
behavior. In C++, assuming cancellation is implemented via the exception
mechanism, things should be well defined. It goes on to say:
"Note that the specified cleanup handling mechanism is especially tied to
the C language and, while the requirement for a uniform mechanism for
expressing cleanup is language-independent, the mechanism used in other
languages may be quite different. In addition, this mechanism is really
only necessary due to the lack of a real exception mechanism in the C
language, which would be the ideal solution."
This indicates that in other language bindings where exceptions are
available, it's expected that thread cancellation be implemented in terms
of those exceptions. This means obeying the rules of exceptions for those
languages, as doing anything else will leave those languages in a tenuous
state. As a C++ programmer, if I can't rely on cancellation "playing
nice", which means behaving exactly like an actual exception, then I can't
rely on cancellation at all, and must disable it. That's the situation
today, since there's no standard C++ binding for POSIX or any other
threading library. Ignoring the standards for a moment, if you're trying
to implement POSIX threads in a manner that's safe for C++, even if it's a
non-standard platform extension (which is a noble goal in and of itself),
you should go the full way in doing this. The one example I know of where
this has been done is on Tru64 (which is not to say other's haven't done
it as well)... and thread cancellation is fully implemented in terms of
exceptions there, even in C. This means you can catch the exception (even
in C) and can stop it's propagation.
>From another thread: http://gcc.gnu.org/ml/gcc-patches/2003-04/msg02285.html
>> 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
Is cancellation defined to be equivalent? The Open Group publication
defines them with the same verbiage with regard to cleanup, but they
aren't totally equivalent and certainly not defined in terms of one
another. In any event, I also don't see anything specifically preventing
pthread_exit from not actually terminating the thread, and on Tru64 this
should even be possible! Of course, it would be a violation of the
implied contract, and as such would be a programmer error... but the
situation is a little different for cancellation. The purpose of
pthread_exit is to terminate with a result, while cancellation is just a
mechanism by which a secondary thread can request that the current thread
end gracefully. Ending gracefully in C++ means running destructors and
catch blocks *in the same manner in which they are run for any other
Just to add another monkey wrench to the whole discussion, ponder this
snippet of code:
foo(); // calls a cancellation point
Some interesting links on this whole topic:
William E. Kempf