Make backtrace support optional
I'm using anyhow for error management in an environment where I care about the binary size. Managing contexts explicitly lets me use rustc's panic=abort mode without significantly reducing ease of debugging, as the "stacktrace" is provided by anyhow. panic=abort would typically greatly reduce binary size because libunwind would no longer need to be linked in. However, anyhow still brings in std::backtrace, which relies on libunwind internally, reducing the benefits of panic=abort.
Would it be possible (or desired) to add an opt-in feature to avoid using std::backtrace, as if RUST_BACKTRACE=0 was always set? Alternatively, what about making backtrace an opt-out feature?
On a second thought, std pulls in libunwind even with panic=abort, so perhaps patching anyhow wouldn't achieve a thing. I guess this is blocked by rust-std support. I think I might try to fix that -- is anyone aware of an existing issue, by any change?
I just realized it isn't blocked by rust-std, actually. The same issue can be reproduced with panic_immediate_abort, in which case anyhow is the only dependency pulling in libunwind.
Prior discussions: #239, #256.
Note: dependence on backtraces also complicate compilation on exotic targets that require -Zbuild-std and does not have backtrace-related symbols like _Unwind_Backtrace available out of the box.
See this discussion on Rust forums. If panic tracebacks are enabled with RUST_BACKTRACE=1, anyhow starts attaching tracebacks to every Error object by default. The program cannot prevent this.
The whole idea that non-panic library behavior depends on an environment variable is just wrong. If you catch an error in code and handle it, the backtrace is useless, but uses time. Anything that does considerable network I/O and uses anyhow will generate large numbers of useless backtraces as it handles I/O errors.
On the forums, dumping "anyhow" and using "thiserror" has been suggested.
I think it's very important that a library using anyhow can choose to disable backtraces without setting an env variable. Libraries should never set env variables for several reasons including 1) setting the variable impacts the app and its use of other libraries, 2) due to the UB warnings in set_var itself and the probability that set_var will be made unsafe in the future.
I've seen the argument that cargo features are opt-in, thus there can't be a feature that disables backtraces. I think that's a narrow way to view the problem. Indeed, std supports the panic_immediate_abort feature just fine. I think the main reason std has this allowance is that only the final bin crate is supposed to use this feature, after proving/verifying/assume the software works just fine without smart panic handling. Therefore, I believe a feature to disable backtrace could work just fine if it was explicitly documented to only be used by the bin crate.
It may even be not a Cargo feature, just a custom cfg attribute, like Tokio's tokio_unstable.
That would prevent intermediate libraries setting this mode, and would require a dedicated compilation setting in project.
The scenario I was referring to was where a library needs to avoid creation of backtraces in errors, and this should not be under the control of the app. The URLO discussion linked above was about this use case.
Right. There are many uses of anyhow! that are not followed by an immediate abort. Capturing a backtrace is for unexpected program bugs. If a program handles an error, or just logs it, there's little need for a backtrace. Certainly not one that goes past the point where the error was handled.
If panic tracebacks are enabled with RUST_BACKTRACE=1, anyhow starts attaching tracebacks to every Error object by default.
RUST_LIB_BACKTRACE=0 should disable this. It can be set using std::env::set_var(), but be aware that in the next edition this function will be marked as unsafe due to not being thread safe on unix systems.
https://docs.rs/anyhow/latest/anyhow/struct.Error.html#method.backtrace
if you want only panics to have backtraces, set
RUST_BACKTRACE=1andRUST_LIB_BACKTRACE=0.