48
48
49
49
#![ allow( dead_code) ]
50
50
51
- use failure;
52
51
use os;
53
52
use thunk:: Thunk ;
54
53
use kinds:: Send ;
@@ -73,52 +72,24 @@ mod macros;
73
72
// These should be refactored/moved/made private over time
74
73
pub mod util;
75
74
pub mod unwind;
75
+ pub mod args;
76
76
77
- mod args;
78
77
mod at_exit_imp;
79
78
mod libunwind;
80
79
81
80
/// The default error code of the rust runtime if the main task panics instead
82
81
/// of exiting cleanly.
83
82
pub const DEFAULT_ERROR_CODE : int = 101 ;
84
83
85
- /// One-time runtime initialization.
86
- ///
87
- /// Initializes global state, including frobbing
88
- /// the crate's logging flags, registering GC
89
- /// metadata, and storing the process arguments.
90
- // FIXME: this should be unsafe
91
- #[ allow( experimental) ]
92
- pub fn init ( argc : int , argv : * const * const u8 ) {
93
- unsafe {
94
- args:: init ( argc, argv) ;
95
- thread:: init ( ) ;
96
- unwind:: register ( failure:: on_fail) ;
97
- }
98
- }
99
-
100
84
#[ cfg( any( windows, android) ) ]
101
- static OS_DEFAULT_STACK_ESTIMATE : uint = 1 << 20 ;
85
+ const OS_DEFAULT_STACK_ESTIMATE : uint = 1 << 20 ;
102
86
#[ cfg( all( unix, not( android) ) ) ]
103
- static OS_DEFAULT_STACK_ESTIMATE : uint = 2 * ( 1 << 20 ) ;
87
+ const OS_DEFAULT_STACK_ESTIMATE : uint = 2 * ( 1 << 20 ) ;
104
88
105
89
#[ cfg( not( test) ) ]
106
90
#[ lang = "start" ]
107
91
fn lang_start ( main : * const u8 , argc : int , argv : * const * const u8 ) -> int {
108
92
use mem;
109
- start ( argc, argv, Thunk :: new ( move || {
110
- let main: extern "Rust" fn ( ) = unsafe { mem:: transmute ( main) } ;
111
- main ( ) ;
112
- } ) )
113
- }
114
-
115
- /// Executes the given procedure after initializing the runtime with the given
116
- /// argc/argv.
117
- ///
118
- /// This procedure is guaranteed to run on the thread calling this function, but
119
- /// the stack bounds for this rust task will *not* be set. Care must be taken
120
- /// for this function to not overflow its stack.
121
- pub fn start ( argc : int , argv : * const * const u8 , main : Thunk ) -> int {
122
93
use prelude:: * ;
123
94
use rt;
124
95
@@ -131,40 +102,59 @@ pub fn start(argc: int, argv: *const *const u8, main: Thunk) -> int {
131
102
// frames above our current position.
132
103
let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE ;
133
104
134
- // By default, some platforms will send a *signal* when a EPIPE error would
135
- // otherwise be delivered. This runtime doesn't install a SIGPIPE handler,
136
- // causing it to kill the program, which isn't exactly what we want!
137
- //
138
- // Hence, we set SIGPIPE to ignore when the program starts up in order to
139
- // prevent this problem.
140
- #[ cfg( windows) ] fn ignore_sigpipe ( ) { }
141
- #[ cfg( unix) ] fn ignore_sigpipe ( ) {
142
- use libc;
143
- use libc:: funcs:: posix01:: signal:: signal;
144
- unsafe {
145
- assert ! ( signal( libc:: SIGPIPE , libc:: SIG_IGN ) != -1 ) ;
105
+ let failed = unsafe {
106
+ // First, make sure we don't trigger any __morestack overflow checks,
107
+ // and next set up our stack to have a guard page and run through our
108
+ // own fault handlers if we hit it.
109
+ sys_common:: stack:: record_os_managed_stack_bounds ( my_stack_bottom,
110
+ my_stack_top) ;
111
+ sys:: thread:: guard:: init ( ) ;
112
+ sys:: stack_overflow:: init ( ) ;
113
+
114
+ // Next, set up the current Thread with the guard information we just
115
+ // created. Note that this isn't necessary in general for new threads,
116
+ // but we just do this to name the main thread and to give it correct
117
+ // info about the stack bounds.
118
+ let thread: Thread = NewThread :: new ( Some ( "<main>" . into_string ( ) ) ) ;
119
+ thread_info:: set ( ( my_stack_bottom, my_stack_top) ,
120
+ sys:: thread:: guard:: main ( ) ,
121
+ thread) ;
122
+
123
+ // By default, some platforms will send a *signal* when a EPIPE error
124
+ // would otherwise be delivered. This runtime doesn't install a SIGPIPE
125
+ // handler, causing it to kill the program, which isn't exactly what we
126
+ // want!
127
+ //
128
+ // Hence, we set SIGPIPE to ignore when the program starts up in order
129
+ // to prevent this problem.
130
+ #[ cfg( windows) ] fn ignore_sigpipe ( ) { }
131
+ #[ cfg( unix) ] fn ignore_sigpipe ( ) {
132
+ use libc;
133
+ use libc:: funcs:: posix01:: signal:: signal;
134
+ unsafe {
135
+ assert ! ( signal( libc:: SIGPIPE , libc:: SIG_IGN ) != -1 ) ;
136
+ }
146
137
}
147
- }
148
- ignore_sigpipe ( ) ;
149
-
150
- init ( argc, argv) ;
151
- let mut exit_code = None ;
152
-
153
- let thread: Thread = NewThread :: new ( Some ( "<main>" . into_string ( ) ) ) ;
154
- thread_info:: set ( ( my_stack_bottom, my_stack_top) ,
155
- unsafe { sys:: thread:: guard:: main ( ) } ,
156
- thread) ;
157
- let mut main_opt = Some ( main) ; // option dance
158
- unsafe {
159
- let _ = unwind:: try ( || {
160
- sys_common:: stack:: record_os_managed_stack_bounds ( my_stack_bottom, my_stack_top) ;
161
- ( main_opt. take ( ) . unwrap ( ) ) . invoke ( ) ;
162
- exit_code = Some ( os:: get_exit_status ( ) ) ;
138
+ ignore_sigpipe ( ) ;
139
+
140
+ // Store our args if necessary in a squirreled away location
141
+ args:: init ( argc, argv) ;
142
+
143
+ // And finally, let's run some code!
144
+ let res = unwind:: try ( || {
145
+ let main: fn ( ) = mem:: transmute ( main) ;
146
+ main ( ) ;
163
147
} ) ;
164
148
cleanup ( ) ;
149
+ res. is_err ( )
150
+ } ;
151
+
152
+ // If the exit code wasn't set, then the try block must have panicked.
153
+ if failed {
154
+ rt:: DEFAULT_ERROR_CODE
155
+ } else {
156
+ os:: get_exit_status ( )
165
157
}
166
- // If the exit code wasn't set, then the task block must have panicked.
167
- return exit_code. unwrap_or ( rt:: DEFAULT_ERROR_CODE ) ;
168
158
}
169
159
170
160
/// Enqueues a procedure to run when the runtime is cleaned up
0 commit comments