[cpp-threads] pthread_cancel and EH: let's try this again

Peter Dimov pdimov at mmltd.net
Mon Jul 11 18:29:48 BST 2005


Some comments...

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 (...).
>
> And the current status quo in GCC:
> 3) #1, except that the destructor for the exception calls abort().
> Additional inelegant possibilities for the destructor would be
> killing just the thread, throwing a new exception, or doing nothing
> (leaving the thread in a sort of zombie state).

1. Boost.Threads doesn't support cancellation. Very possibly never will.

2. The arguments in favor of ... not catching the cancellation exception can 
be summarized as:

2a. We can break perfectly valid catch(...)+rethrow cleanup code because 
it's inelegant.

2b. Some people that use catch(...) don't really want catch(...) semantics.

3. Non-empty exception specifications may terminate() on cancellation. 
(These are even less elegant than catch+rethrow, of course.)

This is also true in cases where the original code avoided terminate() by 
remapping exceptions:

void f() throw( MyException )
{
    try
    {
        g();
    }
    catch( MyException const & )
    {
        throw;
    }
    catch( ... )
    {
        throw MyBadException();
    }
}

(Remapping via unexpected() will work, though, if the cancellation exception 
plays by the rules.)

4. Inter-language communication is usually done by translating the exception 
into a return code, squeezing that through an extern "C" interface, then 
optionally throwing at the other end. It isn't just catch and rethrow 
something else.

5. Disabling cancellation during empty exception specs is too coarse:

int f() throw()
{
    try
    {
        return lengthy_operation();
    }
    catch(...)
    {
        return EXCEPTION;
    }
}

I want cancellation to be active during lengthy_operation.

Summary:

I'm in favor of 1 minus the "destructor reasserts" part (it's not needed). 
I'm undecided on whether the cancellation request is (implicitly) cleared 
when the cancellation exception is thrown. There are good arguments in favor 
of either approach, and a reasonable compromise would be to not clear the 
cancellation request and provide a function for clearing it explicitly for 
the cases where this is desired.

Finally,

> People who want model #1 can use a different threading library, such as
> Boost.Threads.

this is impossible on a number of levels. :-)





More information about the cpp-threads mailing list