123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- use prelude::*;
- use core::sync::atomic::{self, AtomicPtr};
- use core::mem;
- use shim::config;
- #[cfg(feature = "tls")]
- use tls;
- static OOM_HANDLER: AtomicPtr<()> = AtomicPtr::new(config::default_oom_handler as *mut ());
- #[cfg(feature = "tls")]
- tls! {
-
- static THREAD_OOM_HANDLER: MoveCell<Option<fn() -> !>> = MoveCell::new(None);
- }
- pub fn oom() -> ! {
-
- #[cfg(feature = "tls")]
- {
- if let Some(handler) = THREAD_OOM_HANDLER.with(|x| x.replace(None)) {
- log!(DEBUG, "Calling the local OOM handler.");
- handler();
- }
- }
- log!(DEBUG, "Calling the global OOM handler.");
- unsafe {
-
-
- (mem::transmute::<_, fn() -> !>(OOM_HANDLER.load(atomic::Ordering::SeqCst)))()
- }
- }
- #[inline]
- pub fn set_oom_handler(handler: fn() -> !) {
- log!(NOTE, "Setting the global OOM handler.");
- OOM_HANDLER.store(handler as *mut (), atomic::Ordering::SeqCst);
- }
- #[inline]
- #[cfg(feature = "tls")]
- pub fn set_thread_oom_handler(handler: fn() -> !) {
- log!(NOTE, "Setting the thread OOM handler.");
- THREAD_OOM_HANDLER.with(|thread_oom| {
-
- let old = thread_oom.replace(Some(handler));
-
- if old.is_some() {
- log!(WARNING, "An old thread OOM handler was overriden.");
- }
- });
- }
- #[cfg(test)]
- mod test {
- use super::*;
- #[test]
- #[should_panic]
- fn panic_oom() {
- fn panic() -> ! {
- panic!("cats are not cute.");
- }
- set_oom_handler(panic);
- oom();
- }
- #[test]
- #[should_panic]
- #[cfg(feature = "tls")]
- fn panic_thread_oom() {
- fn infinite() -> ! {
- #[allow(empty_loop)]
- loop {}
- }
- fn panic() -> ! {
- panic!("cats are not cute.");
- }
- set_oom_handler(infinite);
- set_thread_oom_handler(panic);
- oom();
- }
- }
|