]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/mod.rs
rollup merge of #20482: kmcallister/macro-reform
[rust.git] / src / libstd / rt / mod.rs
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
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
19 #![experimental]
20
21 // FIXME: this should not be here.
22 #![allow(missing_docs)]
23
24 #![allow(dead_code)]
25
26 use kinds::Send;
27 use ops::FnOnce;
28 use sys;
29 use thunk::Thunk;
30
31 // Reexport some of our utilities which are expected by other crates.
32 pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
33 pub use self::unwind::{begin_unwind, begin_unwind_fmt};
34
35 // Reexport some functionality from liballoc.
36 pub use alloc::heap;
37
38 // Simple backtrace functionality (to print on panic)
39 pub mod backtrace;
40
41 // Internals
42 #[cfg_attr(stage0, macro_escape)]
43 #[cfg_attr(not(stage0), macro_use)]
44 mod macros;
45
46 // These should be refactored/moved/made private over time
47 pub mod util;
48 pub mod unwind;
49 pub mod args;
50
51 mod at_exit_imp;
52 mod libunwind;
53
54 /// The default error code of the rust runtime if the main thread panics instead
55 /// of exiting cleanly.
56 pub const DEFAULT_ERROR_CODE: int = 101;
57
58 #[cfg(any(windows, android))]
59 const OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
60 #[cfg(all(unix, not(android)))]
61 const OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
62
63 #[cfg(not(test))]
64 #[lang = "start"]
65 fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
66     use prelude::v1::*;
67
68     use mem;
69     use os;
70     use rt;
71     use sys_common::thread_info::{self, NewThread};
72     use sys_common;
73     use thread::Thread;
74
75     let something_around_the_top_of_the_stack = 1;
76     let addr = &something_around_the_top_of_the_stack as *const int;
77     let my_stack_top = addr as uint;
78
79     // FIXME #11359 we just assume that this thread has a stack of a
80     // certain size, and estimate that there's at most 20KB of stack
81     // frames above our current position.
82     let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;
83
84     let failed = unsafe {
85         // First, make sure we don't trigger any __morestack overflow checks,
86         // and next set up our stack to have a guard page and run through our
87         // own fault handlers if we hit it.
88         sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom,
89                                                           my_stack_top);
90         sys::thread::guard::init();
91         sys::stack_overflow::init();
92
93         // Next, set up the current Thread with the guard information we just
94         // created. Note that this isn't necessary in general for new threads,
95         // but we just do this to name the main thread and to give it correct
96         // info about the stack bounds.
97         let thread: Thread = NewThread::new(Some("<main>".to_string()));
98         thread_info::set((my_stack_bottom, my_stack_top),
99                          sys::thread::guard::main(),
100                          thread);
101
102         // By default, some platforms will send a *signal* when a EPIPE error
103         // would otherwise be delivered. This runtime doesn't install a SIGPIPE
104         // handler, causing it to kill the program, which isn't exactly what we
105         // want!
106         //
107         // Hence, we set SIGPIPE to ignore when the program starts up in order
108         // to prevent this problem.
109         #[cfg(windows)] fn ignore_sigpipe() {}
110         #[cfg(unix)] fn ignore_sigpipe() {
111             use libc;
112             use libc::funcs::posix01::signal::signal;
113             unsafe {
114                 assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
115             }
116         }
117         ignore_sigpipe();
118
119         // Store our args if necessary in a squirreled away location
120         args::init(argc, argv);
121
122         // And finally, let's run some code!
123         let res = unwind::try(|| {
124             let main: fn() = mem::transmute(main);
125             main();
126         });
127         cleanup();
128         res.is_err()
129     };
130
131     // If the exit code wasn't set, then the try block must have panicked.
132     if failed {
133         rt::DEFAULT_ERROR_CODE
134     } else {
135         os::get_exit_status()
136     }
137 }
138
139 /// Enqueues a procedure to run when the runtime is cleaned up
140 ///
141 /// The procedure passed to this function will be executed as part of the
142 /// runtime cleanup phase. For normal rust programs, this means that it will run
143 /// after all other threads have exited.
144 ///
145 /// The procedure is *not* executed with a local `Thread` available to it, so
146 /// primitives like logging, I/O, channels, spawning, etc, are *not* available.
147 /// This is meant for "bare bones" usage to clean up runtime details, this is
148 /// not meant as a general-purpose "let's clean everything up" function.
149 ///
150 /// It is forbidden for procedures to register more `at_exit` handlers when they
151 /// are running, and doing so will lead to a process abort.
152 pub fn at_exit<F:FnOnce()+Send>(f: F) {
153     at_exit_imp::push(Thunk::new(f));
154 }
155
156 /// One-time runtime cleanup.
157 ///
158 /// This function is unsafe because it performs no checks to ensure that the
159 /// runtime has completely ceased running. It is the responsibility of the
160 /// caller to ensure that the runtime is entirely shut down and nothing will be
161 /// poking around at the internal components.
162 ///
163 /// Invoking cleanup while portions of the runtime are still in use may cause
164 /// undefined behavior.
165 pub unsafe fn cleanup() {
166     args::cleanup();
167     sys::stack_overflow::cleanup();
168     // FIXME: (#20012): the resources being cleaned up by at_exit
169     // currently are not prepared for cleanup to happen asynchronously
170     // with detached threads using the resources; for now, we leak.
171     // at_exit_imp::cleanup();
172 }