cpptrace
cpptrace copied to clipboard
Rethrow without modifying cpptrace::from_current_exception?
If you've got nested CPPTRACE_TRY/CPPTRACE_CATCH blocks, like this:
CPPTRACE_TRY {
foo();
with_opentelemetry_sub_span([](){
CPPRACE_TRY {
bar();
CPPTRACE_CATCH(const std::exception &e) {
put_exception_on_opentelemetry_span(e, cpptrace::from_current_exception());
throw;
}
});
baz();
} CPPTRACE_CATCH(const std::exception &e) {
put_exception_on_opentelemetry_span(e, cpptrace::from_current_exception());
throw;
}
The second call to put_exception_on_opentelemetry_span sees the backtrace coming from the re-throw in the inner CPPTRACE_CATCH block. It would be nice if we could rethrow without losing the original call stack.
My use case for this is to be able to put error backtraces on OpenTelemetry spans; without something like this, the bottom frame of all but the innermost span would be the re-throw at the top of the previous span.
I actually was able to hack something to make it work for my usecase:
CPPTRACE_CATCH(...) {
// stuff
cpptrace::detail::try_canary extra_cpptrace_canary;
cpptrace::detail::get_trace_switch() = false;
throw;
}
which seems to work... is this something we should expose a macro or function for? CPPTRACE_RETHROW or something?
Hi, I have ran into a situation like this as well where I want to rethrow while preserving the stack. Cpptrace should definitely have some helper for doing this.
It took me a moment to understand the hack you found. That does indeed seem to work, though unfortunately it wouldn't for the CPPTRACE_TRYZ/CPPTRACE_CATCHZ variation.
Another thought is that when flipping the trace switch and rethrowing like this outer catch would see the trace of the original exception but not from where the latest throw originated, which I think can be valuable information. Maybe a rethrow trace could be saved somewhere, with a separate API for accessing it. I'd have to give this more thought.
Another solution might be try to rethrow with an exception object that stores the trace, but this isn't without downsides either.
I think for my use case I don’t really need the trace from where the rethrow happened, but I agree that keeping the whole stack of rethrow backtracks around is nice for completeness sake.
Is this something you’d like to see a PR for, or do you want to mull over the design a bit first?
I'd welcome a PR! We need something that will work for both the Z and non-Z variants of the try/catch macros and something that won't add notably cost in the non-throwing path. This might have to be done with std::exception_ptr trickery but I'm open to various approaches.
OK - I'll try and get to something this week. Thanks for the pointers!
I've implemented a basic utility for this, it'll be part of the next release
Unfortunately because of how Microsoft's STL implements exceptions the exception pointer approach doesn't work and I can't find a decent way to implement this that works on msvc/windows clang.
Alright, I was able to find a better solution that's simpler, more efficient, and works on msvc. It's more similar to the hack you found with setting the trace switch :)
I... did not get around to having crack at this, but I'm very thankful that you did! That looks exactly like what I would have wanted, I'll try switching over to this.
I've released the next version of cpptrace with this functionality