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

Possible to export Frame::resolve_symbol? #690

Open
quagmt opened this issue Jan 11, 2025 · 0 comments
Open

Possible to export Frame::resolve_symbol? #690

quagmt opened this issue Jan 11, 2025 · 0 comments

Comments

@quagmt
Copy link

quagmt commented Jan 11, 2025

Problem

  • I'm using eyre as my error handler and trying to write a custom error handler using eyre hook
  • Basically, a backtrace will be captured when error happens, and will be printed/logged later when handling the error.
  • The problem is that I want to capture the backtrace as unresolved and resolve it later in my custom handler so that passing the error around is cheaper. However, I'm not able to do this because, in order to use resolve, my captured backtrace must be a mutable reference. I also tried to get the backtrace frames and resolve each one manually, but I encountered the same issue: the backtrace frames are not &mut, and the Frame field of BacktraceFrame is not exported to use resolve_symbols method.

Proposed Solution

  • Can BacktraceFrame also have resolve_symbols which call frame.resolve_symbols and return all symbols that have been resolved? It already have symbols method but they are empty if the captured backtrace was unresolved

Example code

struct Hook {
    capture_backtrace: bool,
}

impl Hook {
    fn make_handler(&self, _error: &(dyn Error + 'static)) -> Handler {
        let backtrace = if self.capture_backtrace {
            Some(Backtrace::new_unresolved())
        } else {
            None
        };

        Handler { backtrace }
    }
}

struct Handler {
    // custom configured backtrace capture
    backtrace: Option<Backtrace>,
}

impl EyreHandler for Handler {
    fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            return fmt::Debug::fmt(error, f);
        }

        let errors = iter::successors(Some(error), |error| (*error).source());

        for (ind, error) in errors.enumerate() {
            write!(f, "\n{:>4}: {}", ind, error)?;
        }

        if let Some(backtrace) = self.backtrace.as_ref() {
            writeln!(f, "\n\nBacktrace:\n{:?}", backtrace)?;
            let frames = backtrace.frames();

            for (ind, frame) in frames.iter().enumerate() {
                writeln!(f, "\n{:>4}: {:?}", ind, frame.resolve())?; // cannot resolve because frame is not &mut

                // My workaround
                // let ip = frame.ip();
                // backtrace::resolve(ip, |symbol| {
                //     println!("{:?}", symbol);
                // });

                // Proposed solution
                // let backtrace_symbols = frame.resolve_symbols();
                // println!("{:?}", backtrace_symbols);
            }
        }

        Ok(())
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant