1 //! Runtime services 2 //! 3 //! The `rt` module provides a narrow set of runtime services, 4 //! including the global heap (exported in `heap`) and unwinding and 5 //! backtrace support. The APIs in this module are highly unstable, 6 //! and should be considered as private implementation details for the 7 //! time being. 8 9 #![doc(hidden)] 10 #![deny(unsafe_op_in_unsafe_fn)] 11 #![allow(unused_macros)] 12 13 use crate::std::ffi::CString; 14 15 // Re-export some of our utilities which are expected by other crates. 16 pub use crate::std::panicking::{begin_panic, panic_count}; 17 pub use core::panicking::{panic_display, panic_fmt}; 18 19 use crate::std::sync::Once; 20 use crate::std::sys; 21 use crate::std::sys_common::thread_info; 22 use crate::std::thread::Thread; 23 24 // Prints to the "panic output", depending on the platform this may be: 25 // - the standard error output 26 // - some dedicated platform specific output 27 // - nothing (so this macro is a no-op) 28 macro_rules! rtprintpanic { 29 ($($t:tt)*) => { 30 if let Some(mut out) = crate::std::sys::stdio::panic_output() { 31 let _ = crate::std::io::Write::write_fmt(&mut out, format_args!($($t)*)); 32 } 33 } 34 } 35 36 macro_rules! rtabort { 37 ($($t:tt)*) => { 38 { 39 rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*)); 40 crate::std::sys::abort_internal(); 41 } 42 } 43 } 44 45 macro_rules! rtassert { 46 ($e:expr) => { 47 if !$e { 48 rtabort!(concat!("assertion failed: ", stringify!($e))); 49 } 50 }; 51 } 52 53 macro_rules! rtunwrap { 54 ($ok:ident, $e:expr) => { 55 match $e { 56 $ok(v) => v, 57 ref err => { 58 let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug 59 rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) 60 } 61 } 62 }; 63 } 64 65 // One-time runtime initialization. 66 // Runs before `main`. 67 // SAFETY: must be called only once during runtime initialization. 68 // NOTE: this is not guaranteed to run, for example when Rust code is called externally. 69 // 70 // # The `sigpipe` parameter 71 // 72 // Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to 73 // `SIG_IGN`. Applications have good reasons to want a different behavior 74 // though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that 75 // can be used to select how `SIGPIPE` shall be setup (if changed at all) before 76 // `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889> 77 // for more info. 78 // 79 // The `sigpipe` parameter to this function gets its value via the code that 80 // rustc generates to invoke `fn lang_start()`. The reason we have `sigpipe` for 81 // all platforms and not only Unix, is because std is not allowed to have `cfg` 82 // directives as this high level. See the module docs in 83 // `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe` 84 // has a value, but its value is ignored. 85 // 86 // Even though it is an `u8`, it only ever has 4 values. These are documented in 87 // `compiler/rustc_session/src/config/sigpipe.rs`. 88 #[cfg_attr(test, allow(dead_code))] 89 unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { 90 unsafe { 91 sys::init(argc, argv, sigpipe); 92 93 let main_guard = sys::thread::guard::init(); 94 // Next, set up the current Thread with the guard information we just 95 // created. Note that this isn't necessary in general for new threads, 96 // but we just do this to name the main thread and to give it correct 97 // info about the stack bounds. 98 let thread = Thread::new(Some(rtunwrap!(Ok, CString::new("main")))); 99 thread_info::set(main_guard, thread); 100 } 101 } 102 103 // One-time runtime cleanup. 104 // Runs after `main` or at program exit. 105 // NOTE: this is not guaranteed to run, for example when the program aborts. 106 pub(crate) fn cleanup() { 107 static CLEANUP: Once = Once::new(); 108 CLEANUP.call_once(|| unsafe { 109 // Flush stdout and disable buffering. 110 crate::std::io::cleanup(); 111 // SAFETY: Only called once during runtime cleanup. 112 sys::cleanup(); 113 }); 114 } 115 116 // To reduce the generated code of the new `lang_start`, this function is doing 117 // the real work. 118 #[cfg(not(test))] 119 fn lang_start_internal( 120 main: &(dyn Fn() -> i32 + Sync + crate::std::panic::RefUnwindSafe), 121 argc: isize, 122 argv: *const *const u8, 123 sigpipe: u8, 124 ) -> Result<isize, !> { 125 use crate::std::{mem, panic}; 126 let rt_abort = move |e| { 127 mem::forget(e); 128 rtabort!("initialization or cleanup bug"); 129 }; 130 // Guard against the code called by this function from unwinding outside of the Rust-controlled 131 // code, which is UB. This is a requirement imposed by a combination of how the 132 // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking 133 // mechanism itself. 134 // 135 // There are a couple of instances where unwinding can begin. First is inside of the 136 // `rt::init`, `rt::cleanup` and similar functions controlled by bstd. In those instances a 137 // panic is a std implementation bug. A quite likely one too, as there isn't any way to 138 // prevent std from accidentally introducing a panic to these functions. Another is from 139 // user code from `main` or, more nefariously, as described in e.g. issue #86030. 140 // SAFETY: Only called once during runtime initialization. 141 panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?; 142 let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize) 143 .map_err(move |e| { 144 mem::forget(e); 145 rtabort!("drop of the panic payload panicked"); 146 }); 147 panic::catch_unwind(cleanup).map_err(rt_abort)?; 148 ret_code 149 } 150 151 // #[cfg(not(test))] 152 // #[lang = "start"] 153 // fn lang_start<T: crate::std::process::Termination + 'static>( 154 // main: fn() -> T, 155 // argc: isize, 156 // argv: *const *const u8, 157 // sigpipe: u8, 158 // ) -> isize { 159 // let Ok(v) = lang_start_internal( 160 // &move || crate::std::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(), 161 // argc, 162 // argv, 163 // sigpipe, 164 // ); 165 // v 166 // } 167