[cpp-threads] Re: [c++-pthreads] pthread_cancel and EH: let's try this again

Nathan Sidwell nathan at codesourcery.com
Mon Jul 11 23:04:40 BST 2005


Jason Merrill wrote:

> In previous discussions, my favored solution was:
> 1a) Cancellation is disabled during stack unwinding, to avoid trying to
> throw out of a destructor.
> 1b) Make cancellation a normal exception that can be caught and discarded,
> but have the destructor for the exception re-assert cancellation so that
> the process will begin again at the next cancellation point.
> Apparently this is also the Boost.Threads design.
> 
> Then there's the Ada-equivalent model:
> 2a) Cancellation is disabled during destructors and empty exception specs.
> 2b) Cancellation exceptions are not caught by (...).

I disagree that #2 is preferable.  My view is that #1 is the better solution.

Implementing #2 breaks the C++ idiom that using try {} catch(...) {...; throw;}
is equivalent to using a destructor for cleanups.  It might be frowned upon, but
it exists in the language, and in code.  As I previously wrote, a pathelogical
case, that can only be written with catch (...) is applying va_end on an
exception path (va_end must be called in the same function that called va_start
or va_copy).

If I understand #2a correctly, this will require nothrow functions to disable
and reenable thread cancellation on entry and exit.  This sounds suboptimal.
I suppose it would be possible to determine one was inside a nothrow function
during the stack scanning phase of exception handling, and then not throw the
exception if that were the case.  But this relies on 2-phase unwinding and
restartable exceptions.  And, AFAICT, one would then need to disable thread
cancellation in some manner to prevent attempting to throw the cancellation
request at every subsequent cancellation point met within the nothrow function.

> Ulrich Drepper insists that #1 is impossible, because pthread cancellation
> is an irreversible state change.  But I'm not sure why you can't just flip
> various flags back to where they were before.
Likewise.

> My current inclination is to go with model #2; backwards compatibility
> with code written to work with pthread_cleanup_push/pop seems like a
> powerful argument in its favor.  People who want model #1 can use a
> different threading library, such as Boost.Threads.

This is not a good idea.

My understanding is that posix thread cancellation doesn't address cleanups at
all, Boost.Threads does.  Given we're trying to meld threads and a language with
cleanups, we should endeavour to support all the cleanup mechanisms of the
language and the experience of Boost.Threads, than invent something different.

To summarize, both option 1 and option 2 break somethings and preserve other things.

#1.  Preserves C++'s link between catch (...) {...; throw;} and regular destructors.
     Breaks catch (...) {} at the outermost level of a thread.
     Breaks nothrow functions that call functions that contain cancellation points.

#2.  Allows catch (...) {} at the outermost level to DTRT (probably)
     Breaks (silently) catch (...) {...; throw;}
     Allows nothrow functions to 'just work' in the face of thread cancellation.
     Adds a non-exception path cost to nothrow functions.

IMHO #1 is better, for it also allows us to say 'thread cancellation is
*exactly* like exception handling'.

nathan

-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan at codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk





More information about the cpp-threads mailing list