pthread_cancel and EH: let's try this again

Alexander Terekhov terekhov at web.de
Thu Jul 21 10:47:42 UTC 2005


Peter Dimov wrote:
> 
> Alexander Terekhov wrote:
> 
> > It may partially[*] solve it in the case of dtors (making dtors have
> > implicit throw()-nothing catch-less ES [ES fixed edition so to speak]
> > by default and mandating intelligent cancel delivery would solve it
> > much better and won't inhibit use of cancellation inside dtors), but
> > what about "unwinding" using catch-rethrow "dtors" that can also eat
> > exceptions?
> >
> >   try {
> >     operation();
> >   }
> >   catch(...) {
> >     // End of stack unwinding
> >     try {
> >       cleanup();
> >     }
> >     catch(...) {
> >       // eat exception
> >     }
> >     throw; // Begin of another stack unwinding
> >   }
> 
> The stack unwinding doesn't end when the catch block is entered. That's when
> the exception is "caught" - uncaught_exception() starts returning true - but
> it's not until the catch block ends when the exception is considered
> "finished".

Really? Read the definition. There are different try blocks. Each throw 
expression starts new stack unwinding (if there are any destructors 
on the path to the handler; exception specs and EH termination aside 
for a moment). And, BTW, uncaught_exception() is totally busted because 
in C++ there can be multiple active exceptions.

#include <iostream> 
using namespace std; 

int ex_count = 0; 

int foo(); 

struct object { ~object() { foo(); } }; 

int foo() {
  int ex = ex_count++; 
  try { 
    if (ex < 10) { 
      object obj; 
      std::cout << "throw " << ex << std::endl; 
      throw ex; 
    } 
    else { 
      std::cout << "Okay, enough active exceptions and stack unwindings." << endl; 
    } 
  } 
  catch(int ex_caught) { 
    std::cout << "caught " << ex_caught << std::endl; 
  } 
  return ex; 
} 

int main() {
  return foo(); 
} 

Here we've got ten try blocks, ten throw expressions, and ten "stack 
unwindings".

See also

http://groups.google.de/group/comp.lang.c++.moderated/msg/4b355d902b123bf3
(exception_scope() and active_exception<T>(int))

> 
> > [*] Consider:
> >
> >  struct X {
> >
> >    X() {
> >      pthread_cancel(pthread_self());
> >    }
> >
> >   ~X() throw() {
> >      printf("may go boom");
> >    }
> >
> >  };
> >
> >  int main() {
> >    X x;
> >  }
> 
> Yes, this can terminate() under most "non-intelligent" models, except the
> one where destructors disable cancellation. The cause of the termination is
> the throw() specification, though, not the destructor - you can replace ~X
> with an ordinary function. This is one of the motivating examples for the
> ECANCEL school of thought.

Yes, plus mandated stickiness. The thing is that it doesn't solve anything.
Cancel-unaware code was not designed to deal with cancel delivery in the 
first place. Think of ungetc() and stuff like that. It doesn't matter what
happens afterwards or what's used as reporting mechanism. See it?

regards,
alexander.




More information about the c++-pthreads mailing list