Skip to content

Commit a4d899b

Browse files
committed
Add hooks allowing to override the oom behavior
1 parent 0f4ef00 commit a4d899b

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

src/libstd/alloc.rs

+46-2
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,55 @@
1717
#[doc(inline)] pub use alloc_system::System;
1818
#[doc(inline)] pub use core::alloc::*;
1919

20+
use core::sync::atomic::{AtomicPtr, Ordering};
21+
use core::{mem, ptr};
22+
23+
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
24+
25+
/// Registers a custom OOM hook, replacing any that was previously registered.
26+
///
27+
/// The OOM hook is invoked when an infallible memory allocation fails.
28+
/// The default hook prints a message to standard error and aborts the
29+
/// execution, but this behavior can be customized with the [`set_oom_hook`]
30+
/// and [`take_oom_hook`] functions.
31+
///
32+
/// The hook is provided with a `Layout` struct which contains information
33+
/// about the allocation that failed.
34+
///
35+
/// The OOM hook is a global resource.
36+
pub fn set_oom_hook(hook: fn(Layout) -> !) {
37+
HOOK.store(hook as *mut (), Ordering::SeqCst);
38+
}
39+
40+
/// Unregisters the current OOM hook, returning it.
41+
///
42+
/// *See also the function [`set_oom_hook`].*
43+
///
44+
/// If no custom hook is registered, the default hook will be returned.
45+
pub fn take_oom_hook() -> fn(Layout) -> ! {
46+
let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
47+
if hook.is_null() {
48+
default_oom_hook
49+
} else {
50+
unsafe { mem::transmute(hook) }
51+
}
52+
}
53+
54+
fn default_oom_hook(layout: Layout) -> ! {
55+
rtabort!("memory allocation of {} bytes failed", layout.size())
56+
}
57+
2058
#[cfg(not(test))]
2159
#[doc(hidden)]
2260
#[lang = "oom"]
23-
pub extern fn rust_oom(_: Layout) -> ! {
24-
rtabort!("memory allocation failed");
61+
pub extern fn rust_oom(layout: Layout) -> ! {
62+
let hook = HOOK.load(Ordering::SeqCst);
63+
let hook: fn(Layout) -> ! = if hook.is_null() {
64+
default_oom_hook
65+
} else {
66+
unsafe { mem::transmute(hook) }
67+
};
68+
hook(layout)
2569
}
2670

2771
#[cfg(not(test))]

0 commit comments

Comments
 (0)