This is the mail archive of the gcc-patches@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: [3.3] Followup to C++ forced unwinding


Nathan Myers said:
>> Why are the "thread library maintainers... unwilling to implement it"?
>> What concerns do they have with the implementation?  Why is
>> terminate() considered better?  It seems to me that it only makes
>> things more complex, not safer.
>
> You should understand that we are corresponding with implementers  of
> GNU Libc and Gcc who are building a native Posix thread library  on
> Linux, integrating details of library, code generation and the  kernel
> for best performance.
>
> As I understand it, in this implementation, a variety of operations
> available to a thread before it has been cancelled result in
> undefined behavior if called after the cancellation (including e.g.
> thread_exit() and longjmp()).  The implementers fear that allowing  a
> cancelled thread to run off the end of the catch clause makes it  too
> easy to run into code that evokes some undefined behavior.

OK, this helps me understand... but I need a bit more.  Which standard,
and what clauses, declare this to be undefined behavior, and why?  And
since no standard that I'm aware of speaks towards threading and C++,
aren't you already providing definitions for undefined territory?  Can't
you do the same in this case?  If cancellation is implemented in terms of
exception throwing, why would calls to thread_exit() and longjump() be
problematic to this implementation?  Even if it is impossible to call
these, wouldn't that be something that's the responsibility of the
programmer to ensure isn't done?  Why should simply not re-throwing the
exception cause termination?  Wouldn't it make more sense for the other
calls to call terminate() if the thread were cancelled (which would
require two "flags", one to indicate the cancellation request and one to
indicate the initiation after a cancellation point)?

Sorry, I've come in on the middle of this discussion, and it appears
there's some things I'm not up to speed on.

> Making it too easy for users to evoke undefined behavior leads to
> spurious but insistent bug reports from customers who may be hard to
> put off.  If a user must positively assert that the danger is known  and
> accepted, it gets much more unlikely that she will complain
> about the consequences.
>
> So, we're talking about a compromise.  We know what we want.  They know
> what they're willing to implement.  We just need to agree
> on something that satisfies everyone.  In that light, the question is:
> is set_cancellation_destructor() the best possible compromise,  or is
> something more clever, that would make you happier, possible?

I don't know yet... I need some answers to the above questions.

> The code written thus far runs destructors but skips catch clauses. The
> compromise Jason proposed calls terminate() if a cancellation
> is discarded.  The compromise I proposed does that by default, but can
> be turned off.  Can you do better?

I don't know.  I'm still trying to grasp why terminate() is considered a
good (or even acceptable) choice here.

Just to make sure everyone is aware of it, Mr.Butenhof, a noted POSIX
threading expert, has done work on Tru64 along these very same lines
(http://sources.redhat.com/ml/libc-alpha/1999-08/msg00038.html).  I'm
trying to do the research at this moment to give a definative answer, but
I've never seen an indication that Tru64 has done anything along the lines
of calling terminate() if the cancellation exception were not re-thrown.

>> > A compiler flag, perhaps "-Wrethrow", might enable warnings about
>> falling off the end of a "catch(...)" block.
>>
>> A diagnostic sounds reasonable.  More so than a runtime mechanism that
>> may not be caught in testing.  And such a diagnostic might make sense
>> for all exception types, not just cancellation.
>
> Just so.  The goal is to avoid special semantics and special ways of
> coding for libraries that might be used in threaded programs, so
> that writing exception-safe and thread-safe code are just the same as
> generically good coding.  That's generally impossible in C, but normal
> in C++.

Given that goal, I would think that calling terminate() would NOT be a
valid choice.  This makes the cancellation exception unique, and means
writing exception-safe code and thread-safe code are not the same as
writing "generically good code".

try
{
  foo();
}
catch (...)
{
  // do nothing
}

Perfectly valid and reasonable for exception-safe code, at least in some
use cases.  However, if the cancellation exception can cause a call to
terminate(), the above is no longer reasonable, and as a programmer I'd
have to know whether or not foo() can follow any execution path that leads
to a cancellation point to know if I have to take the precaution to use a
mechanism to turn off the call to terminate().  And what about code that's
already been written like this, and is out of my control to change,
because there was no concern about terminate() being called?

-- 
William E. Kempf



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