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


I should introduce William Kempf to the rest of the readers.
He is the primary author of the Boost C++ threads library.

On Thu, May 01, 2003 at 12:26:36PM -0500, William E. Kempf wrote:
> Nathan Myers said:
> > On Thu, May 01, 2003 at 09:17:22AM -0500, William E. Kempf wrote:
> >> Nathan Myers said:
> 
> >> On what schedule?  Cooperative cancellation is a request, not a
> >> demand. ...
> >
> > There are three parties involved:
> > ... A library can only be coded according to reasonable
> > best-practice rules which the program author must verify are 
> > compatible with its use in the complete program.
> 
> Totally agreement.  My point was, the only party that has control over
> the schedule is the thread being cancelled.  

Exactly.  The author of the complete program can afford to use the 
library only if the library author makes a promise that it will not 
interfere with thread cancellation.  Practically, this can be true 
only if "not interfering" is identical to normal best practice, 
because library authors cannot afford to take into account all kinds 
of special domain requirements and maintain the power-set of versions
for all likely combinations of requirements.

> [...] The "schedule" is conceptual, and requires strict and _explicit_
> cooperation among the parties involved.

...unless this cooperation is the norm, in which case the library 
author must explicitly notify users that a particular library is not 
coded normally.  "Doesn't re-throw unidentified exceptions" is a
property that any library user would have to know about anyhow --
threads or no threads.

> > We have to make sure the rules are clear enough and simple enough
> > that it's practical to meet the needs of both library authors and
> > program authors.
> 
> This is best done by imposing no new requirements on the "cancellation
> exception".  This does not make it any more difficult for the thread
> being cancelled to fullfill the request in a timely manner, and more
> importantly, when compared with altering the exception requirements,
> imposes no restrictions that can actually make it more difficult to
> fullfill the request in a timely and *correct* manner.  (The emphasis
> on correct is due to the cases in which it's necessary, or at least
> less problematic, to eat the exception because of usage requirements,
> such as interaction with languages that can't deal with exceptions.)

Agreed, but see below.
 
> >> Terminating [...] in this case seems like a sledge hammer ...
> >
> > The purpose is to prevent spurious bug reports from users who have
> > corrupted their process state all unawares. ...
> 
> Maybe I'm misunderstanding, but I thought the call to terminate under
> discussion here occurs when the exception is caught but not re-thrown?
> If that's the case, what process state would be corrupted in this
> case?  All invariants should still hold.

Agreed, but see below.

> > I agree that it would be better to make the cancellation event
> > behave as an ordinary exception, but the thread library maintainers
> > seem unwilling to implement it.  Programs that want that behavior
> > would have to add (perhaps) "set_cancellation_destructor(0)" to the
> > common preamble at the beginning of main(), along with the
> > "std::ios::sync_with_stdio(false);" and "signal(SIGPIPE, SIG_IGN);"
> > we are already accustomed to doing. :-P
> 
> 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. 

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?

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?

> > 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++.

Nathan Myers
ncm@cantrip.org


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