Skip to content

Commit ee5009e

Browse files
authored
Rollup merge of #123389 - ChrisDenton:dont-panic-on-startup, r=joboet
Avoid panicking unnecessarily on startup On Windows, in `lang_start` we add an exception handler to catch stack overflows and we also reserve some stack space for the handler. Both of these are useful but they're not strictly necessary. The standard library has to work without them (e.g. if Rust is used from a foreign entry point) and the negative effect of not doing them is limited (i.e. you don't get the friendly stack overflow message). As we really don't want to panic pre-main unless absolutely necessary, it now won't panic on failure. I've added some debug assertions so as to avoid programmer error.
2 parents 504a78e + 7b8f93e commit ee5009e

File tree

3 files changed

+14
-30
lines changed

3 files changed

+14
-30
lines changed

library/std/src/sys/pal/windows/stack_overflow.rs

+11-19
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,12 @@
33
use crate::sys::c;
44
use crate::thread;
55

6-
use super::api;
7-
8-
pub struct Handler;
9-
10-
impl Handler {
11-
pub unsafe fn new() -> Handler {
12-
// This API isn't available on XP, so don't panic in that case and just
13-
// pray it works out ok.
14-
if c::SetThreadStackGuarantee(&mut 0x5000) == 0
15-
&& api::get_last_error().code != c::ERROR_CALL_NOT_IMPLEMENTED
16-
{
17-
panic!("failed to reserve stack space for exception handling");
18-
}
19-
Handler
20-
}
6+
/// Reserve stack space for use in stack overflow exceptions.
7+
pub unsafe fn reserve_stack() {
8+
let result = c::SetThreadStackGuarantee(&mut 0x5000);
9+
// Reserving stack space is not critical so we allow it to fail in the released build of libstd.
10+
// We still use debug assert here so that CI will test that we haven't made a mistake calling the function.
11+
debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling");
2112
}
2213

2314
unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> c::LONG {
@@ -36,9 +27,10 @@ unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POIN
3627
}
3728

3829
pub unsafe fn init() {
39-
if c::AddVectoredExceptionHandler(0, Some(vectored_handler)).is_null() {
40-
panic!("failed to install exception handler");
41-
}
30+
let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler));
31+
// Similar to the above, adding the stack overflow handler is allowed to fail
32+
// but a debug assert is used so CI will still test that it normally works.
33+
debug_assert!(!result.is_null(), "failed to install exception handler");
4234
// Set the thread stack guarantee for the main thread.
43-
let _h = Handler::new();
35+
reserve_stack();
4436
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
#![cfg_attr(test, allow(dead_code))]
22

3-
pub struct Handler;
4-
5-
impl Handler {
6-
pub fn new() -> Handler {
7-
Handler
8-
}
9-
}
10-
3+
pub unsafe fn reserve_stack() {}
114
pub unsafe fn init() {}

library/std/src/sys/pal/windows/thread.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ impl Thread {
4848

4949
extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
5050
unsafe {
51-
// Next, set up our stack overflow handler which may get triggered if we run
52-
// out of stack.
53-
let _handler = stack_overflow::Handler::new();
51+
// Next, reserve some stack space for if we otherwise run out of stack.
52+
stack_overflow::reserve_stack();
5453
// Finally, let's run some code.
5554
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
5655
}

0 commit comments

Comments
 (0)