This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: catch(...) and forced unwind


Jason Merrill <jason@redhat.com> writes:

> On Sat, 13 Dec 2003 19:59:09 -0800, Nathan Myers <ncm@cantrip.org> wrote:
>
>> On Sat, Dec 13, 2003 at 08:20:15AM -0500, David Abrahams wrote:
>>> Jason Merrill <jason@redhat.com> writes:
>>> 
>>> > On Fri, 12 Dec 2003 17:42:27 -0500, David Abrahams 
>>> >
>>> >> 2. There is some documentation somewhere which indicates that one of
>>> >>    the functions called by tf is a "cancellation point" (i.e. may
>>> >>    throw thread cancellation exceptions).  Otherwise, it seems to me,
>>> >>    "this high-level behavior" would not be wrong.
>>> >
>>> > Basically, all of the C library I/O functions are cancellation points.
>>> 
>>> Well, I constider that very surprising. It harms the ability to write
>>> portable code, for reasons explained below.
>>
>> Indeed, it's commmon to declare external C functions "throw()", meaning
>> no exceptions can ever come out of them, and expect the compiler to 
>> optimize accordingly.
>
> And g++ does.  I'm not sure at the moment what we do when a forced unwind
> tries to unwind through a throw(); things don't seem to be working
> properly on my laptop at the moment.  I suspect that we fall back on the
> old semantics, i.e. run explicitly pushed cleanups and kill the thread.
>
>>> > I don't expect writing 'cout << "."' to suppress thread cancellation.
>>> > Do you disagree that this is an extremely surprising side-effect?
>>> 
>>> Yes, I disagree that it's surprising.  I know that iostream operations
>>> won't throw unless you set badbit, and I therefore expect them not to
>>> throw.  
>
> Aha.  I didn't realize that the disagreement was so basic.
>
>> Not throwing is part of iostream's contract.  For the runtime system
>> to arbitrarily change that contract makes any code written to the old 
>> contract indeterminate and likely wrong.
>
> I don't see any such contract.
>
>   17.4.4.8  Restrictions on              [lib.res.on.exception.handling]
>        exception handling
>
> 2 None of the functions from the Standard  C  library  shall  report  an
>   error by throwing an exception,176) unless it calls a program-supplied
>   function that throws an exception.177)
>
> 3 No destructor operation defined in the C++ Standard Library will throw
>   an exception.  Any other functions defined in the C++ Standard Library
>   that  do not have an exception-specification may throw implementation-
>   defined  exceptions  unless otherwise specified.178)
>
> This passage seems to give the implementation the latitude to throw an
> implementation-defined exception from any of the iostream functions, since
> none of them are specified throw().

Of course they couldn't be specified that way, since they are
specified to have throwing behavior which can be turned on and off at
runtime.

I have to admit I am not familiar with the specification of iostreams
- in fact, I try to avoid getting familiar with that part of the
standard. I have been going on the assumption that the specification
of badbit handling counts as "otherwise specified".  If I am wrong
(and I may be) then I take it all back.  Am I?  

>>> Furthermore, throwing against the standard's guarantees undermines
>>> portability.  All code which can run in a cancellable thread now has
>>> to have special knowledge of the behavior of the system it's running
>>> on.  That could mean, for example, that people can't pick up the Boost
>>> libraries and use them inside of a thread.  This effect is bad with
>>> functions people don't *expect* to throw (the C I/O) but the standard
>>> does allow those to throw implementation-defined exceptions.  It's
>>> *really really* bad with functions the standard guarantees won't
>>> throw.
>
> Actually, this is backwards -- the standard doesn't allow the C I/O
> functions to throw any exceptions; see the passage above.  This obviously
> needs to change if we're going to do anything useful with POSIX thread
> cancellation.

Not sure what "anything useful" means.

>>> I think it's not the nature of the exception, but the fact that you're
>>> running in a thread which makes it "outside the scope", since the
>>> standard doesn't cover threading.  Still, the ability to use code in
>>> threads which was written without knowledge of your threading system,
>>> I would think, is crucial.
>
> Oh, I agree.  I'm just skeptical that iostream code throwing a cancellation
> exception would interfere with this ability.

That's reasonable.

>> The population of coders willing to write code just for this one
>> threading system is necessarily small.

Whoa; that was Nathan, not me.

> Which one?  POSIX threads?  I hear they're pretty widespread.  But
> seriously, we have a number of customers writing code for that threading
> system, and asking for this functionality.
>
>> This is a difference from the C world.  With C, no one expects a library 
>> to work right in a threaded program if it wasn't written with that target 
>> in mind.  Contrarily, C++ users routinely expect portable C++ libraries 
>> to be exception- and thread-safe, and an enormous amount of such code
>> has already been written that is.  Changing the semantics of exception 
>> handlers breaks it all.
>
> Nathan, you seem to assume that I'm advocating implicit rethrow.  I'm not.
> I'm only suggesting that cancellation should propagate out of iostream
> code, and suggested several ways that might happen.
>
> Both your and David's replies seem to have amounted to saying that any
> change to current behavior is unacceptable.

Not the way I understand the status quo.  As far as I can tell, what
was described as the current compromise (termination) is unacceptable
to me.  If I've misunderstood what you said I would be willing to
revise my position.

> That isn't very useful.  Just to step back a moment, can we all
> agree that we want pthread cancellation to run C++ cleanups?  

I think so.

> And that we might have to adjust a few things to make that work?

Yes.  The only things I think are crucial here is that functions which
are specified not to throw (or conditions which are specified not to
throw) continue to not throw anything, including cancellation, and
that whatever guarantees functions give about program state in case
they throw an exception also apply if the exception is a thread
cancellation.  Almost without exception (NPI), code that works in the
presence of exceptions does not depend on the meaning of said
exceptions, so giving cancellation exceptions any kind of special
license to violate assumptions made about other exceptions would be
wrong.

>> In the meantime, the ISO committee is discussing a standard threads
>> library for C++, including a cancellation model incompatible with what
>> is being proposed here.  It would be better for everybody involved for 
>> Gcc to match it.
>
> Please elaborate.  I don't see a relevant paper in any of the recent
> mailings.

There ain't nothin'.  The effort to standardize Boost.Threads has been
languishing :(

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]