Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rethrow without modifying cpptrace::from_current_exception? #214

Open
KJTsanaktsidis opened this issue Feb 20, 2025 · 4 comments
Open

Rethrow without modifying cpptrace::from_current_exception? #214

KJTsanaktsidis opened this issue Feb 20, 2025 · 4 comments
Labels
enhancement New feature or request

Comments

@KJTsanaktsidis
Copy link

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?

@jeremy-rifkin
Copy link
Owner

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.

@jeremy-rifkin jeremy-rifkin added the enhancement New feature or request label Feb 20, 2025
@KJTsanaktsidis
Copy link
Author

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?

@jeremy-rifkin
Copy link
Owner

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.

@KJTsanaktsidis
Copy link
Author

OK - I'll try and get to something this week. Thanks for the pointers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants