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


On Wed, 2003-04-30 at 22:34, Ulrich Drepper wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Mark Mitchell wrote:
> 
> > Maybe you could point me at the source code for one of these thread
> > library implementations where (1) holds, but (2) does not?
> 
> Just look at the code.
> 
> Cancellation is idempotent.  Therefore a flag is set so that
> cancellation cannot happen in cancellation handlers.  If the program
> continues cancellation won't be possible anymore and the program can get
> stuck.  pthread_exit() doesn't work anymore is one other thing.  In
> other implementation (maybe even in LinuxThreads) you get endless loops
> of calling cleanup handlers.

Cancellation doesn't occur again, even if you call a cancellation point.
You can't call pthread_exit.

A program calling pthread_join may wait arbitrarily long for the
cancelled thread to exit.

That's POSIX threads for you.  It makes no difference whether or not
these things happen from within a pthread_cleanup_push function that
happens to run for a long time, a pthread_key_create destructor that
happens to run for a long time, or a catch handler that chooses not to
rethrow the exception.

If the catch handler chooses not to rethrow the exception, one of a few
things will happen:

(1) The process dies.

(2) The thread runs forever.

(3) The thread misbehaves by calling pthread_exit, or some other
function it's no longer allowed to call.

(4) At some point the thread will return from the main thread function.

Only (4) requires any special handling in the threads library, and the
special handling required is not complex: run pthread_key_create
destructors that have not yet been run, and terminate the thread.

It's perfectly reasonable to argue that catch-clauses should, by
default, rethrow.  Likewise, it's reasonable to argue that "break"
should be the default after a case label, and that "extern void f()"
should mean "extern void f(void)" rather than "extern void f(...)".

C++ programmers understand that "catch (...)" should usually rethrow in
the same way that C programmers know that "break" should usually be
inserted before a case label.  As with fall-through case-statements,
however, it is sometimes reasonable just to catch the exception.

--

The most useful things for pthread cancellation to do in C++ is to throw
an ordinary exception of some type "pthread_cancellation" with no
special semantics whatsoever.

The reason the current compromise is acceptable is that it provides a
forward-compatible subset of that functionality:

- You can't catch that particular exception type, but you can catch it 
  with catch (...).  If the exception later gets the type
  pthread_cancellation, then all of your catch (...) handlers will still
  catch it, but you'll also be able to catch just thread-cancellation
  exceptions.

- You can't choose not to rethrow the exception, nor can you choose to 
  rethrow an exception of a different type -- but in these circumstances
  your process will die; therefore, when the more useful semantics are 
  provided all processes that did not die before will still not die.

This compromise will not do what C++ programmers want, and it will still
prevent them from using many exception-safe libraries in multi-threaded
programs, but some libraries may work, and at least the failure mode for
the others will be relatively obvious.

-- 
Mark Mitchell <mark@codesourcery.com>
CodeSourcery, LLC


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