]>
Commit | Line | Data |
---|---|---|
970d7e83 LB |
1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
1a4d82fc JJ |
11 | //! Runtime services |
12 | //! | |
13 | //! The `rt` module provides a narrow set of runtime services, | |
14 | //! including the global heap (exported in `heap`) and unwinding and | |
15 | //! backtrace support. The APIs in this module are highly unstable, | |
16 | //! and should be considered as private implementation details for the | |
17 | //! time being. | |
18 | ||
62682a34 SL |
19 | #![unstable(feature = "rt", |
20 | reason = "this public module should not exist and is highly likely \ | |
21 | to disappear")] | |
1a4d82fc JJ |
22 | #![allow(missing_docs)] |
23 | ||
c34b1796 | 24 | use prelude::v1::*; |
1a4d82fc | 25 | use sys; |
c34b1796 | 26 | use usize; |
1a4d82fc JJ |
27 | |
28 | // Reexport some of our utilities which are expected by other crates. | |
c1a9b12d | 29 | pub use self::util::min_stack; |
1a4d82fc JJ |
30 | pub use self::unwind::{begin_unwind, begin_unwind_fmt}; |
31 | ||
32 | // Reexport some functionality from liballoc. | |
33 | pub use alloc::heap; | |
34 | ||
35 | // Simple backtrace functionality (to print on panic) | |
36 | pub mod backtrace; | |
37 | ||
38 | // Internals | |
39 | #[macro_use] | |
40 | mod macros; | |
41 | ||
42 | // These should be refactored/moved/made private over time | |
43 | pub mod util; | |
44 | pub mod unwind; | |
45 | pub mod args; | |
46 | ||
47 | mod at_exit_imp; | |
48 | mod libunwind; | |
49 | ||
c1a9b12d SL |
50 | mod dwarf; |
51 | ||
1a4d82fc JJ |
52 | /// The default error code of the rust runtime if the main thread panics instead |
53 | /// of exiting cleanly. | |
c34b1796 | 54 | pub const DEFAULT_ERROR_CODE: isize = 101; |
1a4d82fc JJ |
55 | |
56 | #[cfg(any(windows, android))] | |
c34b1796 | 57 | const OS_DEFAULT_STACK_ESTIMATE: usize = 1 << 20; |
1a4d82fc | 58 | #[cfg(all(unix, not(android)))] |
c34b1796 | 59 | const OS_DEFAULT_STACK_ESTIMATE: usize = 2 * (1 << 20); |
1a4d82fc JJ |
60 | |
61 | #[cfg(not(test))] | |
62 | #[lang = "start"] | |
c34b1796 | 63 | fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { |
1a4d82fc JJ |
64 | use prelude::v1::*; |
65 | ||
66 | use mem; | |
85aaf69f | 67 | use env; |
1a4d82fc JJ |
68 | use rt; |
69 | use sys_common::thread_info::{self, NewThread}; | |
70 | use sys_common; | |
71 | use thread::Thread; | |
72 | ||
73 | let something_around_the_top_of_the_stack = 1; | |
c34b1796 AL |
74 | let addr = &something_around_the_top_of_the_stack as *const _ as *const isize; |
75 | let my_stack_top = addr as usize; | |
1a4d82fc JJ |
76 | |
77 | // FIXME #11359 we just assume that this thread has a stack of a | |
78 | // certain size, and estimate that there's at most 20KB of stack | |
79 | // frames above our current position. | |
c34b1796 AL |
80 | const TWENTY_KB: usize = 20000; |
81 | ||
82 | // saturating-add to sidestep overflow | |
83 | let top_plus_spill = if usize::MAX - TWENTY_KB < my_stack_top { | |
84 | usize::MAX | |
85 | } else { | |
86 | my_stack_top + TWENTY_KB | |
87 | }; | |
88 | // saturating-sub to sidestep underflow | |
89 | let my_stack_bottom = if top_plus_spill < OS_DEFAULT_STACK_ESTIMATE { | |
90 | 0 | |
91 | } else { | |
92 | top_plus_spill - OS_DEFAULT_STACK_ESTIMATE | |
93 | }; | |
1a4d82fc JJ |
94 | |
95 | let failed = unsafe { | |
96 | // First, make sure we don't trigger any __morestack overflow checks, | |
97 | // and next set up our stack to have a guard page and run through our | |
98 | // own fault handlers if we hit it. | |
99 | sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom, | |
100 | my_stack_top); | |
c1a9b12d | 101 | let main_guard = sys::thread::guard::init(); |
1a4d82fc JJ |
102 | sys::stack_overflow::init(); |
103 | ||
104 | // Next, set up the current Thread with the guard information we just | |
105 | // created. Note that this isn't necessary in general for new threads, | |
106 | // but we just do this to name the main thread and to give it correct | |
107 | // info about the stack bounds. | |
108 | let thread: Thread = NewThread::new(Some("<main>".to_string())); | |
c1a9b12d | 109 | thread_info::set(main_guard, thread); |
1a4d82fc JJ |
110 | |
111 | // By default, some platforms will send a *signal* when a EPIPE error | |
112 | // would otherwise be delivered. This runtime doesn't install a SIGPIPE | |
113 | // handler, causing it to kill the program, which isn't exactly what we | |
114 | // want! | |
115 | // | |
116 | // Hence, we set SIGPIPE to ignore when the program starts up in order | |
117 | // to prevent this problem. | |
118 | #[cfg(windows)] fn ignore_sigpipe() {} | |
119 | #[cfg(unix)] fn ignore_sigpipe() { | |
120 | use libc; | |
121 | use libc::funcs::posix01::signal::signal; | |
122 | unsafe { | |
c34b1796 | 123 | assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0); |
970d7e83 | 124 | } |
970d7e83 | 125 | } |
1a4d82fc JJ |
126 | ignore_sigpipe(); |
127 | ||
128 | // Store our args if necessary in a squirreled away location | |
129 | args::init(argc, argv); | |
130 | ||
131 | // And finally, let's run some code! | |
132 | let res = unwind::try(|| { | |
133 | let main: fn() = mem::transmute(main); | |
134 | main(); | |
135 | }); | |
136 | cleanup(); | |
137 | res.is_err() | |
138 | }; | |
139 | ||
140 | // If the exit code wasn't set, then the try block must have panicked. | |
141 | if failed { | |
142 | rt::DEFAULT_ERROR_CODE | |
143 | } else { | |
62682a34 SL |
144 | #[allow(deprecated)] |
145 | fn exit_status() -> isize { env::get_exit_status() as isize } | |
146 | exit_status() | |
970d7e83 | 147 | } |
1a4d82fc | 148 | } |
970d7e83 | 149 | |
c34b1796 | 150 | /// Enqueues a procedure to run when the main thread exits. |
1a4d82fc | 151 | /// |
c34b1796 AL |
152 | /// Currently these closures are only run once the main *Rust* thread exits. |
153 | /// Once the `at_exit` handlers begin running, more may be enqueued, but not | |
154 | /// infinitely so. Eventually a handler registration will be forced to fail. | |
1a4d82fc | 155 | /// |
c34b1796 AL |
156 | /// Returns `Ok` if the handler was successfully registered, meaning that the |
157 | /// closure will be run once the main thread exits. Returns `Err` to indicate | |
158 | /// that the closure could not be registered, meaning that it is not scheduled | |
159 | /// to be rune. | |
160 | pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> { | |
161 | if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} | |
970d7e83 LB |
162 | } |
163 | ||
1a4d82fc JJ |
164 | /// One-time runtime cleanup. |
165 | /// | |
166 | /// This function is unsafe because it performs no checks to ensure that the | |
167 | /// runtime has completely ceased running. It is the responsibility of the | |
168 | /// caller to ensure that the runtime is entirely shut down and nothing will be | |
169 | /// poking around at the internal components. | |
170 | /// | |
171 | /// Invoking cleanup while portions of the runtime are still in use may cause | |
172 | /// undefined behavior. | |
173 | pub unsafe fn cleanup() { | |
174 | args::cleanup(); | |
175 | sys::stack_overflow::cleanup(); | |
c34b1796 | 176 | at_exit_imp::cleanup(); |
970d7e83 | 177 | } |