1

I have the following terminate handler:

void on_terminate() 
{
    std::exception_ptr eptr = std::current_exception();
    if (eptr)
    {
        try
        {
            std::rethrow_exception(eptr);
        }
        catch (const std::exception& e) 
        {
            DBG_FAIL(e.what());        
        }
        catch (...) 
        {
            DBG_FAIL("Unknown exception.");  
        }
    }
    else
    {
        DBG_FAIL("Terminate was called.");
    }    
}

I have been using this handler for a while now and I strongly believe that it worked. But recently it appears that when an exception is throw unhanded I still end up at "Terminate was called.". (I still get a useful call stack.)

I am experiencing the issue on VS2015 Up3 and did not yet have time to check other compilers and platforms. (GCC on Cygwin does not implement exception_ptr yet.) Am I doing something fundamentally wrong?

Given the following code:

int main(int argc, char* argv[]) 
{
    std::set_terminate(on_terminate);

    throw std::runtime_error("#yolo");
}

You can test the issue.

For completeness here you can find my dbg.h.

rioki
  • 5,988
  • 5
  • 32
  • 55
  • 1
    Possible dupe http://stackoverflow.com/questions/28757161/can-a-terminate-handler-throw-an-exception –  Mar 21 '17 at 20:23
  • 1
    No, since eptr is null. The refereed question is about rethrowing with no active exception. This question is more specifically about std::current_exception() returns null from a terminate handler. (But thank you for the effort.) – rioki Mar 21 '17 at 20:32

1 Answers1

1

Not sure what the standard says about this, but it doesn't work with VS2017 either. You can get the desired behavior by doing:

int main(int argc, char* argv[]) try
{
    std::set_terminate(on_terminate);

    throw std::runtime_error("#yolo");
}
catch (...) {
    std::get_terminate()();
}

Which will call your terminate method from within a catch, and the std::current_exception() in your on_terminate will then work.

evan
  • 1,463
  • 1
  • 10
  • 13
  • Except, I loose the call stack. Although there is about 8 lines of junk in the call stack, so far all implementations of compiler I have seen MSC, GCC, Clang, have the entire call stack up to the point where the exception is thrown. To me that info is more valuable than the exception's message. – rioki Mar 21 '17 at 20:41
  • 1
    Yep, that's true. I got nothing then. The standard doesn't seem to be very precise. It states that `std::current_exception` returns the exception currently being handled and that `std::terminate` is called when no handler is found, but I don't see anything that says that an exception is still being handled when `std::terminate` is called. – evan Mar 21 '17 at 21:04
  • Yes, I fear that this is the case. That is quite unfortunate, because that case a nice piece of code. It got the callstack AND the exception msg. Since I only let the "this can not happen" cases throw into main, the callstack has prio over the message. I will mark this answer as the accepted one. – rioki Mar 22 '17 at 19:00
  • 2
    For what it's worth, it seems that both gcc and Clang do it the right way, and from section 15.3.7 of the C++11 standard states that an implicit handler is considered active when `std::terminate` or `std::unexpected` is called. It seems that VS is wrong, and I did find a bug on msconnect, but it was closed as a duplicate and I can't find the duplicate. – evan Mar 23 '17 at 00:35
  • Thank you for the clarification. – rioki Mar 30 '17 at 06:52
  • The point of `set_terminate` is that it could catch exceptions thrown from static initialization constructors, something that wrapping `main` in a try-block won't help with. – Yakov Galka Mar 11 '19 at 02:18
  • @ybungalobill And how would you call set_terminate in time for it to be active while static initialization is happening? – evan Mar 29 '19 at 21:02
  • @evan: by putting it in a constructor of a static object. Statics are guaranteed to be initialized in order within one translation unit. Same way `std::ios_base::Init` work. – Yakov Galka Mar 29 '19 at 21:16