-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add Backtrace::set_enabled to override environment variables #79085
Conversation
r? @KodrAus (rust_highfive has picked a reviewer for you, use r? to override) |
cc @sfackler since you were against this on the internals discussion. |
I don’t want to misrepresent @sfackler here, but it seems like they’re just trying to tease out alternatives rather than necessarily being against this. In apps that I ship I just always have backtraces enabled. I would be interested to see a case where it’s important enough to capture backtraces to the point that you’d build infrastructure to control it remotely, but not enough to do so by default and avoid the need for that infrastructure entirely. Having said that, this does seem pretty reasonable to me! Maybe we can land it, leave it unstable and see if it does find use. |
Also cc @rust-lang/project-error-handling |
One idea I had for a potential usecase that this doesn't support well: being able to enable backtraces for a specific request in a protocol like HTTP. You could imagine having a flag that is parsed early on and enables backtraces for the rest of the processing of a request. In a threaded or async server this would be somewhat complicated to pull off with this API (you would need a guard that does reference counting of how many requests currently want backtraces, and set/unset them globally based on that). Having a thread-local flag (which could be turned into a task-local flag with existing async adaptors) would be more flexible for cases like this, but would need a more complicated design (probably a thread-local override, that can be cleared to fallback to the global setting). The fact that this could be supported now, even with a somewhat complicated reference counting mechanism, means I think it's worth leaving that support up to a library. |
My initial reaction is that instead of having an override setting the entire |
Yeah - I am not entirely opposed to doing this. I just generally feel bad about there only being this "big hammer" approach to backtraces being enabled. That being said, RUST_BACKTRACE is already a big hammer and this just provides a bit more flexibility there so I think it's fine. Though a more configurable hook like @yaahc suggested would be preferable, but I'm not sure exactly what the hook would be able to work with for context. |
@KodrAus any updates? |
/// Explicitly enable or disable backtrace capturing, overriding the default | ||
/// derived from the `RUST_BACKTRACE` or `RUST_LIB_BACKTRACE` environment | ||
/// variables. | ||
pub fn set_enabled(enabled: bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's put an unstable
attribute on this, since we've got #72981 open to stabilize the core backtrace API.
I'm ok with merging this as unstable and shift conversation onto a tracking issue for a more complete design. We should add a test at least that when we call |
I think we might want to hold off on merging this for at least a little because I think it might conflict with the work I'm doing in #77384. In particular, one of the designs I'm investigating rn might supersede this eventually: /// Global implementation of backtrace functinality. Called to create
/// `RawBacktrace` trait objects.
extern {
#[linkage = "extern_weak"]
#[link_name = "__rust_backtrace_impl"]
static BACKTRACE_IMPL: *mut &'static dyn BacktraceImpl;
}
// perma(?)-unstable
#[unstable(feature = "core_backtrace", issue = "74465")]
pub trait BacktraceImpl: 'static {
fn capture(&self) -> *mut dyn RawBacktrace;
fn enabled(&self) -> bool;
}
// perma(?)-unstable
#[unstable(feature = "core_backtrace", issue = "74465")]
pub trait RawBacktrace: fmt::Debug + fmt::Display + 'static {
unsafe fn drop_and_free(self: *mut Self);
}
#[unstable(feature = "core_backtrace", issue = "74465")]
pub struct Backtrace {
inner: *mut dyn RawBacktrace,
} Note: this is super WIP rn and just an example of the direction I'm going |
I haven't had time to update it, so that's fine with me 😁. I've been watching #77384 so when that's looking a bit more stable I'll try rebasing over it and see how it affects this API. |
I'll mark this one as blocked just so we know it's waiting on #77384 |
☔ The latest upstream changes (presumably #92216) made this pull request unmergeable. Please resolve the merge conflicts. |
There is another important reason: There is a consensus that Importantly, they need a replacement that works not just for the library backtraces but also for backtraces for panics. In #90308 @Nemo157 wrote:
I don't fully understand that comment, but it seems to mean that even if this PR is merged, the resultant API still wouldn't be sufficient for applications (like the ones I help maintain) to replace their |
Back in November, 2020, @Nemo157 wrote:
and more recently @KodrAus wrote:
Because of the
|
/// Explicitly enable or disable backtrace capturing, overriding the default | ||
/// derived from the `RUST_BACKTRACE` or `RUST_LIB_BACKTRACE` environment | ||
/// variables. | ||
pub fn set_enabled(enabled: bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This API doesn't look sufficient enough to handle the full functionality of what RUST_BACKTRACE
can do, as RUST_BACKTRACE
has multiple values, and might even be extended to more in the future. I think it would be good to at least change this to take an enum, something like this:
#[non_exhaustive]
pub Enum {
Off,
Short,
Full,
}
Also, I think that this API should be "set at most once," similar to log::set_logger
, as an application like the one I maintain doesn't want a (third-party) library to change this value after we set it in main()
. (The ability to lock the backtrace level is another motivation for adding this new API.)
@briansmith I don't think @rust-lang/libs-api would necessarily object to the narrow introduction of an API to configure the things that are otherwise configured via the environment, separately from the full backtrace feature. It'll take some design, though. |
I've posted #93101 with a larger API surface and discussion of concerns/thoughts raised on this thread. |
…r=yaahc Support configuring whether to capture backtraces at runtime Tracking issue: rust-lang#93346 This adds a new API to the `std::panic` module which configures whether and how the default panic hook will emit a backtrace when a panic occurs. After discussion with `@yaahc` on [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/backtrace.20lib.20vs.2E.20panic), this PR chooses to avoid adjusting or seeking to provide a similar API for the (currently unstable) std::backtrace API. It seems likely that the users of that API may wish to expose more specific settings rather than just a global one (e.g., emulating the `env_logger`, `tracing` per-module configuration) to avoid the cost of capture in hot code. The API added here could plausibly be copied and/or re-exported directly from std::backtrace relatively easily, but I don't think that's the right call as of now. ```rust mod panic { #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub enum BacktraceStyle { Short, Full, Off, } fn set_backtrace_style(BacktraceStyle); fn get_backtrace_style() -> Option<BacktraceStyle>; } ``` Several unresolved questions: * Do we need to move to a thread-local or otherwise more customizable strategy for whether to capture backtraces? See [this comment](rust-lang#79085 (comment)) for some potential use cases for this. * Proposed answer: no, leave this for third-party hooks. * Bikeshed on naming of all the options, as usual. * Should BacktraceStyle be moved into `std::backtrace`? * It's already somewhat annoying to import and/or re-type the `std::panic::` prefix necessary to use these APIs, probably adding a second module to the mix isn't worth it. Note that PR rust-lang#79085 proposed a much simpler API, but particularly in light of the desire to fully replace setting environment variables via `env::set_var` to control the backtrace API, a more complete API seems preferable. This PR likely subsumes that one.
…yaahc Support configuring whether to capture backtraces at runtime Tracking issue: rust-lang#93346 This adds a new API to the `std::panic` module which configures whether and how the default panic hook will emit a backtrace when a panic occurs. After discussion with `@yaahc` on [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/backtrace.20lib.20vs.2E.20panic), this PR chooses to avoid adjusting or seeking to provide a similar API for the (currently unstable) std::backtrace API. It seems likely that the users of that API may wish to expose more specific settings rather than just a global one (e.g., emulating the `env_logger`, `tracing` per-module configuration) to avoid the cost of capture in hot code. The API added here could plausibly be copied and/or re-exported directly from std::backtrace relatively easily, but I don't think that's the right call as of now. ```rust mod panic { #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub enum BacktraceStyle { Short, Full, Off, } fn set_backtrace_style(BacktraceStyle); fn get_backtrace_style() -> Option<BacktraceStyle>; } ``` Several unresolved questions: * Do we need to move to a thread-local or otherwise more customizable strategy for whether to capture backtraces? See [this comment](rust-lang#79085 (comment)) for some potential use cases for this. * Proposed answer: no, leave this for third-party hooks. * Bikeshed on naming of all the options, as usual. * Should BacktraceStyle be moved into `std::backtrace`? * It's already somewhat annoying to import and/or re-type the `std::panic::` prefix necessary to use these APIs, probably adding a second module to the mix isn't worth it. Note that PR rust-lang#79085 proposed a much simpler API, but particularly in light of the desire to fully replace setting environment variables via `env::set_var` to control the backtrace API, a more complete API seems preferable. This PR likely subsumes that one.
I'm going to go ahead and close this in light of #93346 and the PR which made that tracking issue -- I think new experimentation in this space would want to take a fresh start based on the discussions there, and keeping this open then doesn't seem like it is the right step. |
Implements the API discussed in https://internals.rust-lang.org/t/backtrace-libstd-runtime-enable-disable/13268.
A couple of quotes for reasons why this should be configurable outside just the default environment variables:
The reason this needs to be globally configurable is to support deeply enabling backtraces created by libraries, e.g. ones exposed through
Error::backtrace
. An application could useBacktrace::{force_capture, disabled}
along with checking against its ownenabled
flag, but that would only control points at which it might capture backtraces itself, not backtraces that may be passed back from external libraries.It might make sense to also expose
Backtrace::enabled()
publicly with this, that would avoid the cost of having to callBacktrace::capture().status() != BacktraceStatus::Disabled
to detect the current state (though would not give any indication of whether it will be supported or not).(Given that #72981 is close to merging, it's probably best to delay this till that is done and I can create a separate feature flag for it, just wanted to get discussion rolling already).