-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
default OOM handler: use non-unwinding panic, to match std handler #106045
Conversation
r? @nagisa (rustbot has picked a reviewer for you, use r? to override) |
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
aa7ade6
to
896a4e3
Compare
The default OOM handler should not abort when |
Technically, a no-unwind panic is still a panic (and it's an unstable flag anyway), so you can argue that it still meets the letter of the request. Probably, though, the more reasonable behavior would be for You can argue it should be a three-way switch where Footnotes
|
Copying over a bit of rationale from #66741 for clarity:
The intent of this PR IIUC isn't to change This PR merely switches the default no_std oom handler from causing a may-unwind panic to causing a mayn't-unwind panic. The std oom handler (and thus It could make sense to make |
Indeed this PR has little to do with -Zoom. That flag affects the std alloc error handler; this PR changes the default no_std alloc error handler.
|
I want to clarify: With this change, no_std + alloc that encounters OOM will abort without calling the panic handler? |
With this change it will call the panic handler, but the panic handler will be told that it must abort and may not unwind. If it attempts to unwind anyway, this will result in another aborting panic, just like when trying to unwind out of an |
The question is: after |
An OOM panic should probably default to doing the same that any other panic would do, as set by the target profile or the |
This PR is about no_std situations, where |
Your entire argument to make this change is to make default OOM handler consistent with std OOM handler. And |
I am mostly concerned with consistency for what happens on stable.
|
And my concern is about what will happen after |
That's the part I don't get. We have a discrepancy now between the behavior of std since 1.0 and the soon-to-be-stable behavior of no_std. Hypothetical future stabilizations IMO make no difference at all for this discussion. Even if We should probably not stabilize |
Would it be okay if we switch the default OOM handler later to do a normal panic, after we stabilise BTW, a panic-no-unwind is pretty useless for no_std applications, because can_unwind on |
Until |
896a4e3
to
8650f01
Compare
I would hope that we only stabilize this flag after figuring out how to make it affect both the std and no_std default OOM handler. (And even that is still confusing since custom OOM handlers could ignore the flag. But that's a discussion for the -Zoom tracking issue, if such a thing exists.) Or maybe by "stabilise -Zoom=panic" you mean changing the std handler to panic (with unwind) rather than abort by default? If we do that then yes we should definitely also change the no_std default handler to panic (with unwind). |
It is currently not possible for no_std code to unwind on stable for multiple reasons, but the main one is that the unwinding machinery is currently only implemented in I would like to see OOM move towards being treated like a normal panic that goes through the panic handler. This unifies the |
That would mean that no message will be printed at all about the memory exhaustion as the initial panic that should print this message allocates before the panic message is printed. A dedicated allocation failure handler can avoid allocating entirely while printing. #0 __GI___libc_malloc (bytes=1) at malloc.c:3031
#1 0x000055555556d5f9 in alloc::alloc::alloc () at library/alloc/src/alloc.rs:99
#2 alloc::alloc::Global::alloc_impl () at library/alloc/src/alloc.rs:181
#3 alloc::alloc::{impl#1}::allocate () at library/alloc/src/alloc.rs:241
#4 alloc::raw_vec::RawVec::allocate_in<u8, alloc::alloc::Global> () at library/alloc/src/raw_vec.rs:185
#5 alloc::raw_vec::RawVec::with_capacity_in<u8, alloc::alloc::Global> () at library/alloc/src/raw_vec.rs:131
#6 alloc::vec::Vec::with_capacity_in<u8, alloc::alloc::Global> () at library/alloc/src/vec/mod.rs:673
#7 alloc::slice::hack::{impl#1}::to_vec<u8, alloc::alloc::Global> () at library/alloc/src/slice.rs:157
#8 alloc::slice::hack::to_vec<u8, alloc::alloc::Global> () at library/alloc/src/slice.rs:106
#9 alloc::slice::{impl#0}::to_vec_in<u8, alloc::alloc::Global> () at library/alloc/src/slice.rs:436
#10 alloc::slice::{impl#0}::to_vec<u8> () at library/alloc/src/slice.rs:411
#11 std::sys::unix::os::getenv () at library/std/src/sys/unix/os.rs:557
#12 std::env::_var_os () at library/std/src/env.rs:273
#13 0x000055555556e50f in std::env::var_os<&str> () at library/std/src/env.rs:269
#14 std::panic::get_backtrace_style () at library/std/src/panic.rs:298
#15 0x0000555555570d63 in std::panicking::default_hook () at library/std/src/panicking.rs:241
#16 0x0000555555571948 in std::panicking::rust_panic_with_hook () at library/std/src/panicking.rs:688
#17 0x000055555555aa34 in std::panicking::begin_panic::{{closure}} ()
#18 0x000055555555b2a5 in std::sys_common::backtrace::__rust_end_short_backtrace ()
#19 0x000055555555a97f in std::panicking::begin_panic ()
#20 0x000055555555a929 in main () |
Fair. But in that case this PR makes no difference, and I would argue also helps clarify that this will not actually ever unwind. (It also adds some |
I think this PR is mostly fine, but I would like one change to be made. Could you check the value of |
Sure, can do. I was not sure if we could use that symbol in no_std situations. That will negate the |
…et), to match std handler
8650f01
to
5974f6f
Compare
The |
All right, adjusted things as requested. |
In the future, I think it would be nice to eliminate the custom OOM handler in @bors r+ |
Agreed, though it will be tricky to maintain support for EDIT: Actually alloc_error_hook doesn't seem to use anything from std so maybe this would just work?
As in entirely remove that feature? I am confused. |
|
The entire point was to remove the one that is defined in std, and move its implementation inside That sounds like it could cause a bunch of trouble (or at least strange error messages) if panics allocate (e.g. to display the backtrace), but other than that probably should work? Not sure what is even hard about it -- why hasn't it been done? Is it only because prior to non-unwinding panics we couldn't preserve the current default behavior of having an abort (rather than unwind), or is it because printing the backtrace will probably allocate and then things go south? |
I would like to remove the custom handling for OOM entirely and route everything through the panic handler. This already the current behavior with
Sure, but in practice most OOMs are caused by large allocations. Any small allocations in the panic handler are still likely to succeed. In the rare case where it still panics, then it will still safely fall back to an abort (albeit with a confusing error message). |
Oh I see, makes sense. Well, the first step (moving std's |
…mpiler-errors Rollup of 8 pull requests Successful merges: - rust-lang#104748 (Ensure `lld` is supported with `download-ci-llvm`) - rust-lang#105541 (Simplify some iterator combinators) - rust-lang#106045 (default OOM handler: use non-unwinding panic, to match std handler) - rust-lang#106157 (Don't trim path for `unsafe_op_in_unsafe_fn` lints) - rust-lang#106353 (Reduce spans for `unsafe impl` errors) - rust-lang#106381 (Jsondoclint: Add `--verbose` and `--json-output` options) - rust-lang#106411 (rustdoc: remove legacy font-feature-settings CSS) - rust-lang#106414 (Add cuviper to the review rotation for libs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Hello @RalfJung #![no_std]
#![no_main]
extern crate alloc;
use alloc::{boxed::Box, vec};
use libc_alloc::LibcAlloc;
use libc_print::std_name::println;
#[global_allocator]
static GLOBAL_ALLOC: LibcAlloc = LibcAlloc;
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
#[no_mangle]
pub extern "C" fn main() -> i32 {
println!("hello world!");
let test1 = vec![1, 2, 3];
for v in test1 {
println!("{v}")
}
let test2 = Box::new(10);
println!("{test2}");
0
} in nightly-2022-12-29, it works perfectly. but now, it will be link error
can you help resolve this issue in rust 1.68 for our embedded linux developers? thanks very much. cc @Amanieu |
Does it work with |
Hello @nbdd0121 |
So here's why it doesn't work: |
@gngshn Please file a new issue for this |
OK, I will file a new issue, thanks |
The OOM handler in std will by default abort. This adjusts the default in liballoc to do the same, using the
can_unwind
flag on the panic info to indicate a non-unwinding panic.In practice this probably makes little difference since the liballoc default will only come into play in no-std situations where people write a custom panic handler, which most likely will not implement unwinding. But still, this seems more consistent.
Cc @rust-lang/wg-allocators, #66741