pthread_cancel and EH: let's try this again

David Abrahams dave at boost-consulting.com
Mon Jul 11 22:29:25 UTC 2005


Mark Mitchell <mark at codesourcery.com> writes:

> Jason Merrill wrote:
>> Previous discussion on this topic ended in something of a stalemate.
>
> Thank you for re-starting the discussion.  I wasn't happy with the 
> stalemate, but I didn't have the fortitude to try again!
>
>> 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.
>
> I think this is a reasonable solution.
>
> I think I'd still prefer just to have the handler catch the exception 
> and discard it, 

Me too.  I don't see any need to make this exception special.

> but not strongly enough to try to stand in the way of progress.

Me too.  I haven't thought through the arguments about whether this
re-cancel behavior is a good idea.  In fact, I don't know what they
are, so if someone could summarize that would be great.

> If you can build consensus around this option, I'll support 
> it fully.
>
> Both your model, and the variant I suggest, preserve the pleasant 
> property that code which already handles "random" exceptions (like that 
> in libraries designed to plug into applications) continues to behave 
> reasonably well in the presence of cancellation.

Yep, that's important to me.

> Code that doesn't handle random exceptions probably doesn't handle 
> thread-cancellation either; if it's relying on certain functions 
> throwing only certain exceptions, then it's probably written to work in 
> a relatively controlled environment.  (Of course, if it were compiled 
> with headers that say that cancellation point functions throw no 
> exceptions, then it would be completely hosed, under any of these models.)

Unless the code doesn't call any of those cancellation point
functions.

>> 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 think this ought to be considered a non-starter.  Ignoring "catch 
> (...)" blocks in C++ is worse than just killing the thread.  Style 
> considerations aside, there's a ton of code that relies on that to clean 
> up resources, or to otherwise restore state; and running destructors 
> after skipping "catch (...)" blocks is just plain wrong, in my opinion.

Agree.

> Maybe in workstation/server applications this makes sense to some 
> people, but I don't think it makes any sense at all on an embedded 
> system, where the system is often set up to handle complete process 
> death, but not weird inconsistencies.  You'd be breaking people's 
> program verification regimes, as well.

The platform doesn't matter.  Destructors have to be able to rely on
program invariants being maintained, and as you imply, skipping a
catch(...) block in the middle of unwinding is likely to break those
invariants.

>> Thread robustness (catch and retry).  A thread could have a catch (...)
>>   at the top level to try to recover from errors, on the principle that
>>   limping along is better than total failure.  Previous discussion seemed
>>   to assume that the users would want this to catch cancellation as well,
>>   but I think that's wrong; if someone specifically told the thread to go
>>   away, they don't want it to recover, they want it to go away.  
>
> I agree.  In fact, despite my oft-stated opinion that it should be 
> possible to catch cancellation exceptions, I agree that actually doing 
> that -- and never restarting the cancellation process -- would generally 
> be a bug in user code.

Almost.  If the thread (optionally issues some kind of report and)
exits -- an entirely plausible response to an exception ending up in
catch(...)  because you didn't recognize it -- I think that's not
quite bad enough to be a bug, and technically it does not amount to
restarting the cancellation process.  That would entail re-throwing a
cancellation exception IMO.

> The reason I'm OK with catching the exception is to do things like:
>
>   try { ... } catch (Cancellation) {
>     cancelled = 1;
>   }
>   /* Other stuff here.  We have no finally clauses in C++.  */
>   if (cancelled) {
>     throw Cancellation;  // Or, maybe a different exception type, that
>                          // tells the top level to cancel the thread.
>   }

As Peter D. suggested, something similar happens when C++
interoperates with Python (and I'm sure many other systems written in
'C').  Usually "Other stuff here" is actually a few stack frames of
'C' code.

> Your auto-recancel semantics are probably good enough in this kind of 
> situation.

I'd like more detail on how it helps (and of course any arguments
against it too).

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

Agree.

> Yes, I've asked Ulrich about this several times, and have never gotten 
> an explanation.
>
>> 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.
>
> Oh, no...  I thought up until this paragraph that we were going to be on 
> the same page.

Whoa! Me too!

> I think that if #1 really is impossible, #2 might be second-best.  But, 
> I'd very much like an explanation of why #1 is impossible.  While I have 
> very high confidence in Ulrich's technical abilities, I don't think we 
> should have to take his opinions on faith.

Yah.  Number 2 breaks too many programs and libraries that ought to be
correct in the presence of threads.  

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com




More information about the c++-pthreads mailing list