-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Stabilize the backtrace feature. #72981
Conversation
r? @kennytm (rust_highfive has picked a reviewer for you, use r? to override) |
@rfcbot fcp merge |
Team member @withoutboats has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
acbcf8d
to
e610f54
Compare
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Thanks for the write-up! The one thing I would add is trait impls to the list of stabilized APIs. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
@bors r- (just noting this until end of full final comment period, so non team members can raise concerns) |
The comments on how the I would like to see an implementation or at least a detailed design of the hooks that would enable backtrace support in libcore before we stabilize this. @rfcbot concern Error in core |
Can you provide a positive statement of why the backtrace functionality would provide some unique difficulty? Asking others to prove a negative feels unfair. I'm certainly not going to design hooks for this, though I think they would be useful even beyond getting this stabilized (presumably embedded devs do actually want backtraces and can sometimes have them). It's a big project it's not on anyone's roadmap. Meanwhile, real users are currently regressed. The inherent impl issue is a much bigger blocker for moving Error to core. Despite the claim that we could "hack coherence" around it being accepted as a handwave solution, @sfackler has expressed concern about actually doing this and I agree. I certainly am not comfortable ending up in a situation where std defines inherent impls for core types, but they are separate crates, in any permanent capacity. I would be comfortable with that maybe only if it were strongly motivated by user need and coupled with an ongoing plan to merge core and std and remove the coherence hacks. |
I'm would be happy to do a proof of concept to show how this would potentially work to verify that we could infact move Error to core to prove that it works. Am I correct though in assuming that this solution would still require coherence hacks for Assuming we can show with reasonable confidence that we'd be able to move Error to core with |
My main concern that that this would require the |
To be clear, is the new proposal to fully stabilize |
Yes, because the only reason we currently have for moving |
Could all methods to construct a backtrace be moved to an extension trait? That would make moving |
One thing I haven't seen mentioned here is using the Backtrace API in signal handlers. It'd be extremely useful to have it there, especially for SIGSEGV and SIGABRT when you are doing a bunch of FFI with a memory-unsafe language. For example, #79153 is about handling this in the compiler. Since signal handlers can't allocate, I think this boils down to having a |
That would also require the unwinder itself to be async signal safe, which this libunwind is, but I don't think that's specified to be the case for the C++ ABI unwinder that backtrace uses right now. |
We discussed this at the recent Libs meeting and came to the conclusion that stabilizing We can move design discussion over to #77384 |
☔ The latest upstream changes (presumably #81660) made this pull request unmergeable. Please resolve the merge conflicts. |
This replaces the backtrace crate and removes quite a few recursive dependencies. There was a proposal to stabilize backtrace, but it was decided that it is better to wait until the interface with the Error trait is decided. See rust-lang/rust#72981
I have a use case for Backtrace without Error: I want to print the stack in a panic handler. |
I've nominated this for discussion but my first instinct is to suggest using |
I guess backtrace would work. It would be nice to avoid the extra dependency. Is the API for Backtrace still in flux? Or is it unstable only because Error is unstable? |
its still theoretically in flux, in case we decide that the hook based option for exposing the interface from |
We discussed this in today's @rust-lang/libs-api meeting. We felt that we should defer this to allow for a broader recommendation (encompassing this and other things) from the error-handling group, and we felt that there's currently a viable solution available (the backtrace crate). Given that, we don't want to stabilize this at this time. |
Stabilize backtrace This PR stabilizes the std::backtrace module. As of rust-lang#99431, the std::Error::backtrace item has been removed, and so the rest of the backtrace feature is set to be stabilized. Previous discussion can be found in rust-lang#72981, rust-lang#3156. Stabilized API summary: ```rust pub mod std { pub mod backtrace { pub struct Backtrace { } pub enum BacktraceStatus { Unsupported, Disabled, Captured, } impl fmt::Debug for Backtrace {} impl Backtrace { pub fn capture() -> Backtrace; pub fn force_capture() -> Backtrace; pub const fn disabled() -> Backtrace; pub fn status(&self) -> BacktraceStatus; } impl fmt::Display for Backtrace {} } } ``` `@yaahc`
I believe now that #99573 is merged, this can be closed? |
Stabilization Report
This is a proposal to stabilize the
backtrace
feature in libstd. It would make these additional APIs available on stable:The behavior of the backtrace type, especially as it connects to certain environment variables, is better documented in the module documentation: https://doc.rust-lang.org/std/backtrace/index.html
The internal details of how backtraces are captured and represented are platform specific and unspecified. A platform may not support backtraces at all. Libstd's backtrace type will do its best to report a backtrace to the caller of
Backtrace::capture
andBacktrace::force_capture
.Background and Motivation
This API was proposed as part of RFC 2504, which was merged in August 2018. The API was based on experience with the failure crate, released November 2017, and motivated by a longstanding user request for a standardized way to access backtraces, especially in connection with errors that have been raised. This API was implemented actually in September 2019.
In late 2019, many users began migrating from the
failure
crate to crates based onstd::error::Error
, because most of the API changes proposed in RFC 2504 had been stabilized, and new crates similar to failure but based on std Error had been implemented, most notably thiserror and anyhow by dtolnay. In early 2020, the failure crate was deprecated, and users were recommended to use anyhow and thiserror instead.However, on stable, the user experience of anyhow and thiserror is not equivalent to the user experience of failure, because the backtrace component of RFC 2504 has not been stabilized. Some users have been left in the frustrating and confusing experience of watching the ecosystem move around them to a solution that does not have feature parity for them, because they were depending on the backtrace feature of failure. They are forced to either migrate from stable to nightly or manage compatibility issues with the rest of the ecosystem while staying on failure.
Even the anyhow crate only has meaningful backtraces with the backtrace feature of the crate turned on, which in turn depends on the backtrace feature of std.
Unresolved questions from RFC
One unresolved question was left over from the RFC regarding the API of
capture
: some proposed that rather than have backtraces which return a non-Captured
status, the capture API return an Option. This was discussed at length on the RFC, and the RFC was ultimately merged with an unresolved question to confirm that the current design worked well. There has since been no discussion of that aspect of the RFC.Two aspects complicate the idea of having a backtrace's non-pressence indicated with an option:
Error::backtrace
introduce a third reason a backtrace wouldn't be present: the concrete implementation did not try to capture a backtrace.Combined we would be looking at an API like
fn backtrace(&self) -> Option<&Result<Backtrace, BacktraceError>>
, which becomes very unwieldy. For users who need to interrogate a backtrace's materiality, theBacktraceStatus
provides a means of determining if the backtrace they've captured is not meaningful and why.Issues raised during implementation period
Fmt representation #65280
Changes were made to the representation of the backtrace type, removing the header from the display representation & providing a debug implementation which is consistent with other Debug implementations.
However, #65280 also proposes providing a means of limiting the backtrace using something like the precision syntax. This has not been implemented. I propose that this is a desirable feature, but it is strictly add-on and it should not be a blocker on stabilizing backtrace.
Backtrace and Error in core
The main issue raised during implementation was the relationship of
Error::backtrace
andError
not being in core. TheError
trait is already not in core for another reason: an inherent method ondyn Error
requires theBox
type, which is not in core, but stabilizingError::backtrace
would add a second dependence on a non-core type.It is desirable for the
Error
trait to be available from core, and therefore users have expressed concern about adding a new dependency on a non-core type. However, this stabilization would not present any new challenge that could not be resolved as easily as the existing challenges:Because the existing issue with Error would already require a language-level change to allow std to add an inherent method to
dyn Error
, which multiple team members (me included) have expressed concern about doing, this does not seem to me to present a substantial increase in the amount of work needed to make Error available in core.RFC 2895 and "generic member access"
Finally, there is the idea that RFC 2895 could supercede the Error::backtrace method. RFC 2895 provides an API for essentially a specialized dynamically dispatched "generic member" that errors could have, which is core-compatible. Such an API could then be used to provide the backtrace, or any other dynamically dispatched type, that an error could contain.
However, this RFC is not merged or in FCP, and is still in the early phases of design. We have already soft-regressed users, who have been relying on an existing API that has been in design for several years. Blocking the resolution of those users' problems on an RFC in early design stages would not be prudent.
The basic motivation of RFC 2895 is that it allows errors to provide many different kinds of contexts, not just a backtrace, and in a way which is open ended and extensible. This may be a desirable property for the std error trait, and RFC 2895 may eventually be merged, stabilized, etc. However, I would contend that even in such a case, preferential treatment for backtraces is still desirable. Backtraces are a standard feature provided not only in Rust but in many language ecosystems, which users have come to expect. Providing a first-class method for getting the backtrace, called backtrace, even if it delegates to a more generic "request for context" method in the long term, makes sense for the optimal user experience.
Future work
Other than the future work on the error trait discussed above, there is future work to be done on the backtrace type. In particular, the backtrace type currently provides no method of analysis other than debug and display printing the backtrace. It would be beneficial to provide a platform agnostic, standard API for iterating over the frames of the backtrace and the members of the frames in the long term. Such an API would justify a separate RFC.