| //! Runtime services | 
 | //! | 
 | //! The `rt` module provides a narrow set of runtime services, | 
 | //! including the global heap (exported in `heap`) and unwinding and | 
 | //! backtrace support. The APIs in this module are highly unstable, | 
 | //! and should be considered as private implementation details for the | 
 | //! time being. | 
 |  | 
 | #![unstable( | 
 |     feature = "rt", | 
 |     reason = "this public module should not exist and is highly likely \ | 
 |               to disappear", | 
 |     issue = "none" | 
 | )] | 
 | #![doc(hidden)] | 
 | #![deny(unsafe_op_in_unsafe_fn)] | 
 | #![allow(unused_macros)] | 
 |  | 
 | #[rustfmt::skip] | 
 | pub use crate::panicking::{begin_panic, panic_count}; | 
 | pub use core::panicking::{panic_display, panic_fmt}; | 
 |  | 
 | #[rustfmt::skip] | 
 | use crate::any::Any; | 
 | use crate::sync::Once; | 
 | use crate::thread::{self, main_thread}; | 
 | use crate::{mem, panic, sys}; | 
 |  | 
 | // This function is needed by the panic runtime. | 
 | #[cfg(not(test))] | 
 | #[rustc_std_internal_symbol] | 
 | fn __rust_abort() { | 
 |     crate::process::abort(); | 
 | } | 
 |  | 
 | // Prints to the "panic output", depending on the platform this may be: | 
 | // - the standard error output | 
 | // - some dedicated platform specific output | 
 | // - nothing (so this macro is a no-op) | 
 | macro_rules! rtprintpanic { | 
 |     ($($t:tt)*) => { | 
 |         #[cfg(not(panic = "immediate-abort"))] | 
 |         if let Some(mut out) = crate::sys::stdio::panic_output() { | 
 |             let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*)); | 
 |         } | 
 |         #[cfg(panic = "immediate-abort")] | 
 |         { | 
 |             let _ = format_args!($($t)*); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | macro_rules! rtabort { | 
 |     ($($t:tt)*) => { | 
 |         { | 
 |             rtprintpanic!("fatal runtime error: {}, aborting\n", format_args!($($t)*)); | 
 |             crate::process::abort(); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | macro_rules! rtassert { | 
 |     ($e:expr) => { | 
 |         if !$e { | 
 |             rtabort!(concat!("assertion failed: ", stringify!($e))); | 
 |         } | 
 |     }; | 
 | } | 
 |  | 
 | macro_rules! rtunwrap { | 
 |     ($ok:ident, $e:expr) => { | 
 |         match $e { | 
 |             $ok(v) => v, | 
 |             ref err => { | 
 |                 let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug | 
 |                 rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) | 
 |             } | 
 |         } | 
 |     }; | 
 | } | 
 |  | 
 | fn handle_rt_panic<T>(e: Box<dyn Any + Send>) -> T { | 
 |     mem::forget(e); | 
 |     rtabort!("initialization or cleanup bug"); | 
 | } | 
 |  | 
 | // One-time runtime initialization. | 
 | // Runs before `main`. | 
 | // SAFETY: must be called only once during runtime initialization. | 
 | // NOTE: this is not guaranteed to run, for example when Rust code is called externally. | 
 | // | 
 | // # The `sigpipe` parameter | 
 | // | 
 | // Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to | 
 | // `SIG_IGN`. Applications have good reasons to want a different behavior | 
 | // though, so there is a `-Zon-broken-pipe` compiler flag that | 
 | // can be used to select how `SIGPIPE` shall be setup (if changed at all) before | 
 | // `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889> | 
 | // for more info. | 
 | // | 
 | // The `sigpipe` parameter to this function gets its value via the code that | 
 | // rustc generates to invoke `fn lang_start()`. The reason we have `sigpipe` for | 
 | // all platforms and not only Unix, is because std is not allowed to have `cfg` | 
 | // directives as this high level. See the module docs in | 
 | // `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe` | 
 | // has a value, but its value is ignored. | 
 | // | 
 | // Even though it is an `u8`, it only ever has 4 values. These are documented in | 
 | // `compiler/rustc_session/src/config/sigpipe.rs`. | 
 | #[cfg_attr(test, allow(dead_code))] | 
 | unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { | 
 |     #[cfg_attr(target_os = "teeos", allow(unused_unsafe))] | 
 |     unsafe { | 
 |         sys::init(argc, argv, sigpipe) | 
 |     }; | 
 |  | 
 |     // Remember the main thread ID to give it the correct name. | 
 |     // SAFETY: this is the only time and place where we call this function. | 
 |     unsafe { main_thread::set(thread::current_id()) }; | 
 | } | 
 |  | 
 | /// Clean up the thread-local runtime state. This *should* be run after all other | 
 | /// code managed by the Rust runtime, but will not cause UB if that condition is | 
 | /// not fulfilled. Also note that this function is not guaranteed to be run, but | 
 | /// skipping it will cause leaks and therefore is to be avoided. | 
 | pub(crate) fn thread_cleanup() { | 
 |     // This function is run in situations where unwinding leads to an abort | 
 |     // (think `extern "C"` functions). Abort here instead so that we can | 
 |     // print a nice message. | 
 |     panic::catch_unwind(|| { | 
 |         crate::thread::drop_current(); | 
 |     }) | 
 |     .unwrap_or_else(handle_rt_panic); | 
 | } | 
 |  | 
 | // One-time runtime cleanup. | 
 | // Runs after `main` or at program exit. | 
 | // NOTE: this is not guaranteed to run, for example when the program aborts. | 
 | pub(crate) fn cleanup() { | 
 |     static CLEANUP: Once = Once::new(); | 
 |     CLEANUP.call_once(|| unsafe { | 
 |         // Flush stdout and disable buffering. | 
 |         crate::io::cleanup(); | 
 |         // SAFETY: Only called once during runtime cleanup. | 
 |         sys::cleanup(); | 
 |     }); | 
 | } | 
 |  | 
 | // To reduce the generated code of the new `lang_start`, this function is doing | 
 | // the real work. | 
 | #[cfg(not(test))] | 
 | fn lang_start_internal( | 
 |     main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe), | 
 |     argc: isize, | 
 |     argv: *const *const u8, | 
 |     sigpipe: u8, | 
 | ) -> isize { | 
 |     // Guard against the code called by this function from unwinding outside of the Rust-controlled | 
 |     // code, which is UB. This is a requirement imposed by a combination of how the | 
 |     // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking | 
 |     // mechanism itself. | 
 |     // | 
 |     // There are a couple of instances where unwinding can begin. First is inside of the | 
 |     // `rt::init`, `rt::cleanup` and similar functions controlled by std. In those instances a | 
 |     // panic is a std implementation bug. A quite likely one too, as there isn't any way to | 
 |     // prevent std from accidentally introducing a panic to these functions. Another is from | 
 |     // user code from `main` or, more nefariously, as described in e.g. issue #86030. | 
 |     // | 
 |     // We use `catch_unwind` with `handle_rt_panic` instead of `abort_unwind` to make the error in | 
 |     // case of a panic a bit nicer. | 
 |     panic::catch_unwind(move || { | 
 |         // SAFETY: Only called once during runtime initialization. | 
 |         unsafe { init(argc, argv, sigpipe) }; | 
 |  | 
 |         let ret_code = panic::catch_unwind(main).unwrap_or_else(move |payload| { | 
 |             // Carefully dispose of the panic payload. | 
 |             let payload = panic::AssertUnwindSafe(payload); | 
 |             panic::catch_unwind(move || drop({ payload }.0)).unwrap_or_else(move |e| { | 
 |                 mem::forget(e); // do *not* drop the 2nd payload | 
 |                 rtabort!("drop of the panic payload panicked"); | 
 |             }); | 
 |             // Return error code for panicking programs. | 
 |             101 | 
 |         }); | 
 |         let ret_code = ret_code as isize; | 
 |  | 
 |         cleanup(); | 
 |         // Guard against multiple threads calling `libc::exit` concurrently. | 
 |         // See the documentation for `unique_thread_exit` for more information. | 
 |         crate::sys::exit_guard::unique_thread_exit(); | 
 |  | 
 |         ret_code | 
 |     }) | 
 |     .unwrap_or_else(handle_rt_panic) | 
 | } | 
 |  | 
 | #[cfg(not(any(test, doctest)))] | 
 | #[lang = "start"] | 
 | fn lang_start<T: crate::process::Termination + 'static>( | 
 |     main: fn() -> T, | 
 |     argc: isize, | 
 |     argv: *const *const u8, | 
 |     sigpipe: u8, | 
 | ) -> isize { | 
 |     lang_start_internal( | 
 |         &move || crate::sys::backtrace::__rust_begin_short_backtrace(main).report().to_i32(), | 
 |         argc, | 
 |         argv, | 
 |         sigpipe, | 
 |     ) | 
 | } |