diff options
| author | Mike Hommey <mh@glandium.org> | 2018-05-16 09:16:37 +0900 |
|---|---|---|
| committer | Mike Hommey <mh@glandium.org> | 2018-05-30 10:57:38 +0900 |
| commit | a4d899b4a1248f885563e241fa56fe9f69616dc2 (patch) | |
| tree | 4c7f5275e05d8b11bf386aa060f7dc413a0745c8 | |
| parent | 0f4ef003ac1691d04f0ce519d1d78696689534aa (diff) | |
| download | rust-a4d899b4a1248f885563e241fa56fe9f69616dc2.tar.gz rust-a4d899b4a1248f885563e241fa56fe9f69616dc2.zip | |
Add hooks allowing to override the `oom` behavior
| -rw-r--r-- | src/libstd/alloc.rs | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 0c95ceff2e3..4f9dffc7c95 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -17,11 +17,55 @@ #[doc(inline)] pub use alloc_system::System; #[doc(inline)] pub use core::alloc::*; +use core::sync::atomic::{AtomicPtr, Ordering}; +use core::{mem, ptr}; + +static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); + +/// Registers a custom OOM hook, replacing any that was previously registered. +/// +/// The OOM hook is invoked when an infallible memory allocation fails. +/// The default hook prints a message to standard error and aborts the +/// execution, but this behavior can be customized with the [`set_oom_hook`] +/// and [`take_oom_hook`] functions. +/// +/// The hook is provided with a `Layout` struct which contains information +/// about the allocation that failed. +/// +/// The OOM hook is a global resource. +pub fn set_oom_hook(hook: fn(Layout) -> !) { + HOOK.store(hook as *mut (), Ordering::SeqCst); +} + +/// Unregisters the current OOM hook, returning it. +/// +/// *See also the function [`set_oom_hook`].* +/// +/// If no custom hook is registered, the default hook will be returned. +pub fn take_oom_hook() -> fn(Layout) -> ! { + let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); + if hook.is_null() { + default_oom_hook + } else { + unsafe { mem::transmute(hook) } + } +} + +fn default_oom_hook(layout: Layout) -> ! { + rtabort!("memory allocation of {} bytes failed", layout.size()) +} + #[cfg(not(test))] #[doc(hidden)] #[lang = "oom"] -pub extern fn rust_oom(_: Layout) -> ! { - rtabort!("memory allocation failed"); +pub extern fn rust_oom(layout: Layout) -> ! { + let hook = HOOK.load(Ordering::SeqCst); + let hook: fn(Layout) -> ! = if hook.is_null() { + default_oom_hook + } else { + unsafe { mem::transmute(hook) } + }; + hook(layout) } #[cfg(not(test))] |
