tags:

views:

39

answers:

2

I have some clean up in a terminate_handler and it is possible to throw an exception. Do I need to worry about catching it to prevent recursive calls to the terminate_handler? With gcc, it seems this can't happen and we just go into abort. Is that true of the standard or is the behavior undefined?

+1  A: 

No, you cannot resume normal program flow from std::terminate. You can, however, throw a different exception from the unexpected function. Terminate does just that -- program execution terminates after it completes.

EDIT:

That said, you shouldn't be doing anything complicated in std::terminate -- if you're in terminate then things have blown up sufficiently that you should not be trying to continue -- and you shouldn't try to do things like allocate memory in std::terminate for the same reason -- what if the program is in there as a result of a low memory condition? There's nothing you can do about it there.

Billy ONeal
I don't want to resume normal program flow. My handler might look like this void myTerminate(){ logger.consumeAll(); }. It's a last ditch attempt to log what's there. I was wondering what happens if Logger::consumeAll throws.
pythonic metaphor
@Pythonic: Yes, I'm just doing a bad job of explaining what I meant. If that's what you're doing, as GMan says, if it throws you've got undefined behavior.
Billy ONeal
@pythonic: Oh, and just because you don't *want* to resume normal program flow, does not mean that is not what you'd be doing in the event you threw from `std::terminate` ;)
Billy ONeal
@Billy: I didn't appreciate this last point until reading the responses!
pythonic metaphor
+4  A: 

A terminate handler is not allowed to return (§18.6.​3.1/2); it must end the program (the default handler calls abort()). If it consisted of:

void my_terminate()
{
    throw 5;
}

You'd get undefined behavior, because you would leave the function (because the exception propagates) without having terminated the program. So if you have code that could throw, make sure you catch all exceptions, like this:

void my_terminate()
{
    try
    {
        // stuff
    }
    catch(...)
    {
        // too bad
    }

    abort();
}

However (to answer the title question), I don't see anything that restricts it from being entered again, so this should be technically be fine:

void my_terminate()
{
    static int counter = 0;

    if (counter++ < 5)
        terminate();

    abort();
}
GMan
`std::terminate` -- probably the only place `catch (...)` is okay. +1
Billy ONeal