diff options
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/common/mod.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sys/common/stack.rs | 311 | ||||
| -rw-r--r-- | src/libstd/sys/common/thread.rs | 7 | ||||
| -rw-r--r-- | src/libstd/sys/unix/stack_overflow.rs | 72 | ||||
| -rw-r--r-- | src/libstd/sys/unix/thread.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sys/windows/c.rs | 25 | ||||
| -rw-r--r-- | src/libstd/sys/windows/stack_overflow.rs | 102 | ||||
| -rw-r--r-- | src/libstd/sys/windows/thread.rs | 11 |
8 files changed, 85 insertions, 453 deletions
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index b205b6df4cb..d63b66c42c7 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -21,7 +21,6 @@ pub mod io; pub mod poison; pub mod remutex; pub mod rwlock; -pub mod stack; pub mod thread; pub mod thread_info; pub mod thread_local; @@ -52,3 +51,7 @@ pub trait IntoInner<Inner> { pub trait FromInner<Inner> { fn from_inner(inner: Inner) -> Self; } + +#[cfg(stage0)] +#[lang = "stack_exhausted"] +pub fn stack_exhausted() {} diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs deleted file mode 100644 index 41c8ac4aed3..00000000000 --- a/src/libstd/sys/common/stack.rs +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Rust stack-limit management -//! -//! Currently Rust uses a segmented-stack-like scheme in order to detect stack -//! overflow for rust threads. In this scheme, the prologue of all functions are -//! preceded with a check to see whether the current stack limits are being -//! exceeded. -//! -//! This module provides the functionality necessary in order to manage these -//! stack limits (which are stored in platform-specific locations). The -//! functions here are used at the borders of the thread lifetime in order to -//! manage these limits. -//! -//! This function is an unstable module because this scheme for stack overflow -//! detection is not guaranteed to continue in the future. Usage of this module -//! is discouraged unless absolutely necessary. - -// iOS related notes -// -// It is possible to implement it using idea from -// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h -// -// In short: _pthread_{get,set}_specific_direct allows extremely fast -// access, exactly what is required for segmented stack -// There is a pool of reserved slots for Apple internal use (0..119) -// First dynamic allocated pthread key starts with 257 (on iOS7) -// So using slot 149 should be pretty safe ASSUMING space is reserved -// for every key < first dynamic key -// -// There is also an opportunity to steal keys reserved for Garbage Collection -// ranges 80..89 and 110..119, especially considering the fact Garbage Collection -// never supposed to work on iOS. But as everybody knows it - there is a chance -// that those slots will be re-used, like it happened with key 95 (moved from -// JavaScriptCore to CoreText) -// -// Unfortunately Apple rejected patch to LLVM which generated -// corresponding prolog, decision was taken to disable segmented -// stack support on iOS. - -pub const RED_ZONE: usize = 20 * 1024; - -/// This function is invoked from rust's current __morestack function. Segmented -/// stacks are currently not enabled as segmented stacks, but rather one giant -/// stack segment. This means that whenever we run out of stack, we want to -/// truly consider it to be stack overflow rather than allocating a new stack. -#[cfg(not(test))] // in testing, use the original libstd's version -#[lang = "stack_exhausted"] -extern fn stack_exhausted() { - use intrinsics; - - unsafe { - // We're calling this function because the stack just ran out. We need - // to call some other rust functions, but if we invoke the functions - // right now it'll just trigger this handler being called again. In - // order to alleviate this, we move the stack limit to be inside of the - // red zone that was allocated for exactly this reason. - let limit = get_sp_limit(); - record_sp_limit(limit - RED_ZONE / 2); - - // This probably isn't the best course of action. Ideally one would want - // to unwind the stack here instead of just aborting the entire process. - // This is a tricky problem, however. There's a few things which need to - // be considered: - // - // 1. We're here because of a stack overflow, yet unwinding will run - // destructors and hence arbitrary code. What if that code overflows - // the stack? One possibility is to use the above allocation of an - // extra 10k to hope that we don't hit the limit, and if we do then - // abort the whole program. Not the best, but kind of hard to deal - // with unless we want to switch stacks. - // - // 2. LLVM will optimize functions based on whether they can unwind or - // not. It will flag functions with 'nounwind' if it believes that - // the function cannot trigger unwinding, but if we do unwind on - // stack overflow then it means that we could unwind in any function - // anywhere. We would have to make sure that LLVM only places the - // nounwind flag on functions which don't call any other functions. - // - // 3. The function that overflowed may have owned arguments. These - // arguments need to have their destructors run, but we haven't even - // begun executing the function yet, so unwinding will not run the - // any landing pads for these functions. If this is ignored, then - // the arguments will just be leaked. - // - // Exactly what to do here is a very delicate topic, and is possibly - // still up in the air for what exactly to do. Some relevant issues: - // - // #3555 - out-of-stack failure leaks arguments - // #3695 - should there be a stack limit? - // #9855 - possible strategies which could be taken - // #9854 - unwinding on windows through __morestack has never worked - // #2361 - possible implementation of not using landing pads - - ::rt::util::report_overflow(); - - intrinsics::abort(); - } -} - -// Windows maintains a record of upper and lower stack bounds in the Thread Information -// Block (TIB), and some syscalls do check that addresses which are supposed to be in -// the stack, indeed lie between these two values. -// (See https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839) -// -// When using Rust-managed stacks (libgreen), we must maintain these values accordingly. -// For OS-managed stacks (libnative), we let the OS manage them for us. -// -// On all other platforms both variants behave identically. - -#[inline(always)] -pub unsafe fn record_os_managed_stack_bounds(stack_lo: usize, _stack_hi: usize) { - record_sp_limit(stack_lo + RED_ZONE); -} - -/// Records the current limit of the stack as specified by `end`. -/// -/// This is stored in an OS-dependent location, likely inside of the thread -/// local storage. The location that the limit is stored is a pre-ordained -/// location because it's where LLVM has emitted code to check. -/// -/// Note that this cannot be called under normal circumstances. This function is -/// changing the stack limit, so upon returning any further function calls will -/// possibly be triggering the morestack logic if you're not careful. -/// -/// Also note that this and all of the inside functions are all flagged as -/// "inline(always)" because they're messing around with the stack limits. This -/// would be unfortunate for the functions themselves to trigger a morestack -/// invocation (if they were an actual function call). -#[inline(always)] -pub unsafe fn record_sp_limit(limit: usize) { - return target_record_sp_limit(limit); - - #[cfg(all(target_arch = "x86_64", - any(target_os = "macos", target_os = "ios")))] - #[inline(always)] - unsafe fn target_record_sp_limit(limit: usize) { - asm!("movq $$0x60+90*8, %rsi - movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile") - } - #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: usize) { - asm!("movq $0, %fs:112" :: "r"(limit) :: "volatile") - } - #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)] - unsafe fn target_record_sp_limit(_: usize) { - } - #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: usize) { - asm!("movq $0, %fs:24" :: "r"(limit) :: "volatile") - } - #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] - #[inline(always)] - unsafe fn target_record_sp_limit(limit: usize) { - asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile") - } - - #[cfg(all(target_arch = "x86", - any(target_os = "macos", target_os = "ios")))] - #[inline(always)] - unsafe fn target_record_sp_limit(limit: usize) { - asm!("movl $$0x48+90*4, %eax - movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile") - } - #[cfg(all(target_arch = "x86", target_os = "linux"))] - #[inline(always)] - unsafe fn target_record_sp_limit(limit: usize) { - asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile") - } - #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)] - unsafe fn target_record_sp_limit(_: usize) { - } - - // mips, arm - The implementations are a bit big for inline asm! - // They can be found in src/rt/arch/$target_arch/record_sp.S - #[cfg(any(target_arch = "mips", - target_arch = "mipsel", - all(target_arch = "arm", not(target_os = "ios"))))] - #[inline(always)] - unsafe fn target_record_sp_limit(limit: usize) { - use libc::c_void; - return record_sp_limit(limit as *const c_void); - extern { - fn record_sp_limit(limit: *const c_void); - } - } - - // aarch64 - FIXME(AARCH64): missing... - // powerpc - FIXME(POWERPC): missing... - // arm-ios - iOS segmented stack is disabled for now, see related notes - // openbsd/bitrig/netbsd - no segmented stacks. - // x86-freebsd - no segmented stacks. - #[cfg(any(target_arch = "aarch64", - target_arch = "powerpc", - all(target_arch = "arm", target_os = "ios"), - all(target_arch = "x86", target_os = "freebsd"), - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] - unsafe fn target_record_sp_limit(_: usize) { - } -} - -/// The counterpart of the function above, this function will fetch the current -/// stack limit stored in TLS. -/// -/// Note that all of these functions are meant to be exact counterparts of their -/// brethren above, except that the operands are reversed. -/// -/// As with the setter, this function does not have a __morestack header and can -/// therefore be called in a "we're out of stack" situation. -#[inline(always)] -pub unsafe fn get_sp_limit() -> usize { - return target_get_sp_limit(); - - #[cfg(all(target_arch = "x86_64", - any(target_os = "macos", target_os = "ios")))] - #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - let limit; - asm!("movq $$0x60+90*8, %rsi - movq %gs:(%rsi), $0" : "=r"(limit) :: "rsi" : "volatile"); - return limit; - } - #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - let limit; - asm!("movq %fs:112, $0" : "=r"(limit) ::: "volatile"); - return limit; - } - #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - return 1024; - } - #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - let limit; - asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile"); - return limit; - } - #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] - #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - let limit; - asm!("movq %fs:32, $0" : "=r"(limit) ::: "volatile"); - return limit; - } - - #[cfg(all(target_arch = "x86", - any(target_os = "macos", target_os = "ios")))] - #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - let limit; - asm!("movl $$0x48+90*4, %eax - movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile"); - return limit; - } - #[cfg(all(target_arch = "x86", target_os = "linux"))] - #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - let limit; - asm!("movl %gs:48, $0" : "=r"(limit) ::: "volatile"); - return limit; - } - #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - return 1024; - } - - // mips, arm - The implementations are a bit big for inline asm! - // They can be found in src/rt/arch/$target_arch/record_sp.S - #[cfg(any(target_arch = "mips", - target_arch = "mipsel", - all(target_arch = "arm", not(target_os = "ios"))))] - #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - use libc::c_void; - return get_sp_limit() as usize; - extern { - fn get_sp_limit() -> *const c_void; - } - } - - // aarch64 - FIXME(AARCH64): missing... - // powerpc - FIXME(POWERPC): missing... - // arm-ios - no segmented stacks. - // openbsd/bitrig/netbsd - no segmented stacks. - // x86-freebsd - no segmented stacks.. - // - // This function might be called by runtime though - // so it is unsafe to unreachable, let's return a fixed constant. - #[cfg(any(target_arch = "aarch64", - target_arch = "powerpc", - all(target_arch = "arm", target_os = "ios"), - all(target_arch = "x86", target_os = "freebsd"), - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] - #[inline(always)] - unsafe fn target_get_sp_limit() -> usize { - 1024 - } -} diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys/common/thread.rs index d19ef11c01f..16f4f01bf39 100644 --- a/src/libstd/sys/common/thread.rs +++ b/src/libstd/sys/common/thread.rs @@ -13,15 +13,8 @@ use prelude::v1::*; use alloc::boxed::FnBox; use libc; use sys::stack_overflow; -use sys_common::stack; -use usize; -#[no_stack_check] pub unsafe fn start_thread(main: *mut libc::c_void) { - // First ensure that we don't trigger __morestack (also why this has a - // no_stack_check annotation). - stack::record_os_managed_stack_bounds(0, usize::MAX); - // Next, set up our stack overflow handler which may get triggered if we run // out of stack. let _handler = stack_overflow::Handler::new(); diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index ed4e50735a6..4e4cf2b0ed1 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -40,25 +40,17 @@ impl Drop for Handler { target_os = "netbsd", target_os = "openbsd"))] mod imp { - use sys_common::stack; - use super::Handler; use rt::util::report_overflow; use mem; use ptr; - use intrinsics; use sys::c::{siginfo, sigaction, SIGBUS, SIG_DFL, SA_SIGINFO, SA_ONSTACK, sigaltstack, - SIGSTKSZ, sighandler_t, raise}; + SIGSTKSZ, sighandler_t}; use libc; use libc::funcs::posix88::mman::{mmap, munmap}; - use libc::funcs::posix01::signal::signal; - use libc::consts::os::posix88::{SIGSEGV, - PROT_READ, - PROT_WRITE, - MAP_PRIVATE, - MAP_ANON, - MAP_FAILED}; + use libc::{SIGSEGV, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON}; + use libc::MAP_FAILED; use sys_common::thread_info; @@ -66,46 +58,48 @@ mod imp { // This is initialized in init() and only read from after static mut PAGE_SIZE: usize = 0; - #[no_stack_check] + // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages + // (unmapped pages) at the end of every thread's stack, so if a thread ends + // up running into the guard page it'll trigger this handler. We want to + // detect these cases and print out a helpful error saying that the stack + // has overflowed. All other signals, however, should go back to what they + // were originally supposed to do. + // + // This handler currently exists purely to print an informative message + // whenever a thread overflows its stack. When run the handler always + // un-registers itself after running and then returns (to allow the original + // signal to be delivered again). By returning we're ensuring that segfaults + // do indeed look like segfaults. + // + // Returning from this kind of signal handler is technically not defined to + // work when reading the POSIX spec strictly, but in practice it turns out + // many large systems and all implementations allow returning from a signal + // handler to work. For a more detailed explanation see the comments on + // #26458. unsafe extern fn signal_handler(signum: libc::c_int, - info: *mut siginfo, - _data: *mut libc::c_void) { - - // We can not return from a SIGSEGV or SIGBUS signal. - // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html - - unsafe fn term(signum: libc::c_int) -> ! { - use core::mem::transmute; - - signal(signum, transmute(SIG_DFL)); - raise(signum); - intrinsics::abort(); - } - - // We're calling into functions with stack checks - stack::record_sp_limit(0); - + info: *mut siginfo, + _data: *mut libc::c_void) { let guard = thread_info::stack_guard().unwrap_or(0); let addr = (*info).si_addr as usize; - if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard { - term(signum); + // If the faulting address is within the guard page, then we print a + // message saying so. + if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard { + report_overflow(); } - report_overflow(); + // Unregister ourselves by reverting back to the default behavior. + let mut action: sigaction = mem::zeroed(); + action.sa_sigaction = SIG_DFL; + sigaction(signum, &action, ptr::null_mut()); - intrinsics::abort() + // See comment above for why this function returns. } static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void; pub unsafe fn init() { - let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE); - if psize == -1 { - panic!("failed to get page size"); - } - - PAGE_SIZE = psize as usize; + PAGE_SIZE = ::sys::os::page_size(); let mut action: sigaction = mem::zeroed(); action.sa_flags = SA_SIGINFO | SA_ONSTACK; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 67ecd4d9229..ea1bfbd9b7d 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -23,7 +23,6 @@ use ptr; use sys::os; use time::Duration; -use sys_common::stack::RED_ZONE; use sys_common::thread::*; pub struct Thread { @@ -43,8 +42,7 @@ impl Thread { let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(pthread_attr_init(&mut attr), 0); - // Reserve room for the red zone, the runtime's stack of last resort. - let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr)); + let stack_size = cmp::max(stack, min_stack_size(&attr)); match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) { 0 => {} n => { @@ -72,7 +70,6 @@ impl Thread { Ok(Thread { id: native }) }; - #[no_stack_check] extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { unsafe { start_thread(main); } 0 as *mut _ diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 06c14b39e12..8fb03ae7902 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -78,6 +78,10 @@ pub const PROGRESS_QUIET: libc::DWORD = 3; pub const TOKEN_ADJUST_PRIVILEGES: libc::DWORD = 0x0020; pub const SE_PRIVILEGE_ENABLED: libc::DWORD = 2; +pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0; +pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; +pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; + #[repr(C)] #[cfg(target_arch = "x86")] pub struct WSADATA { @@ -327,6 +331,24 @@ pub struct REPARSE_MOUNTPOINT_DATA_BUFFER { pub ReparseTarget: libc::WCHAR, } +#[repr(C)] +pub struct EXCEPTION_RECORD { + pub ExceptionCode: DWORD, + pub ExceptionFlags: DWORD, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: LPVOID, + pub NumberParameters: DWORD, + pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS] +} + +#[repr(C)] +pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ContextRecord: LPVOID +} + +pub type PVECTORED_EXCEPTION_HANDLER = extern "system" + fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; #[link(name = "ws2_32")] #[link(name = "userenv")] @@ -487,6 +509,9 @@ extern "system" { BufferLength: libc::DWORD, PreviousState: PTOKEN_PRIVILEGES, ReturnLength: *mut libc::DWORD) -> libc::BOOL; + pub fn AddVectoredExceptionHandler(FirstHandler: ULONG, + VectoredHandler: PVECTORED_EXCEPTION_HANDLER) + -> LPVOID; } // Functions that aren't available on Windows XP, but we still use them and just diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs index bc8ee6619f1..f93f7c756de 100644 --- a/src/libstd/sys/windows/stack_overflow.rs +++ b/src/libstd/sys/windows/stack_overflow.rs @@ -8,108 +8,44 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[cfg(stage0)] -use core::prelude::v1::*; - -use libc::types::os::arch::extra::{LPVOID, DWORD, LONG}; -use libc; -use mem; -use ptr; +use libc::{self, LONG}; use rt::util::report_overflow; use sys::c; -use sys_common::stack; -pub struct Handler { - _data: *mut libc::c_void -} +pub struct Handler; impl Handler { pub unsafe fn new() -> Handler { - make_handler() + // This API isn't available on XP, so don't panic in that case and just + // pray it works out ok. + if c::SetThreadStackGuarantee(&mut 0x5000) == 0 { + if libc::GetLastError() as u32 != libc::ERROR_CALL_NOT_IMPLEMENTED as u32 { + panic!("failed to reserve stack space for exception handling"); + } + } + Handler } } -impl Drop for Handler { - fn drop(&mut self) {} -} - -// This is initialized in init() and only read from after -static mut PAGE_SIZE: usize = 0; - -#[no_stack_check] -extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG { +extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) + -> LONG { unsafe { let rec = &(*(*ExceptionInfo).ExceptionRecord); let code = rec.ExceptionCode; - if code != EXCEPTION_STACK_OVERFLOW { - return EXCEPTION_CONTINUE_SEARCH; + if code == c::EXCEPTION_STACK_OVERFLOW { + report_overflow(); } - - // We're calling into functions with stack checks, - // however stack checks by limit should be disabled on Windows - stack::record_sp_limit(0); - - report_overflow(); - - EXCEPTION_CONTINUE_SEARCH + c::EXCEPTION_CONTINUE_SEARCH } } pub unsafe fn init() { - let mut info = mem::zeroed(); - libc::GetSystemInfo(&mut info); - PAGE_SIZE = info.dwPageSize as usize; - - if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() { + if c::AddVectoredExceptionHandler(0, vectored_handler).is_null() { panic!("failed to install exception handler"); } - - mem::forget(make_handler()); -} - -pub unsafe fn cleanup() { -} - -pub unsafe fn make_handler() -> Handler { - // This API isn't available on XP, so don't panic in that case and just pray - // it works out ok. - if c::SetThreadStackGuarantee(&mut 0x5000) == 0 { - if libc::GetLastError() as u32 != libc::ERROR_CALL_NOT_IMPLEMENTED as u32 { - panic!("failed to reserve stack space for exception handling"); - } - } - - Handler { _data: 0 as *mut libc::c_void } -} - -#[repr(C)] -pub struct EXCEPTION_RECORD { - pub ExceptionCode: DWORD, - pub ExceptionFlags: DWORD, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: LPVOID, - pub NumberParameters: DWORD, - pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS] + // Set the thread stack guarantee for the main thread. + let _h = Handler::new(); } -#[repr(C)] -pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ContextRecord: LPVOID -} - -pub type PVECTORED_EXCEPTION_HANDLER = extern "system" - fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; - -pub type ULONG = libc::c_ulong; - -const EXCEPTION_CONTINUE_SEARCH: LONG = 0; -const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; -const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; - -extern "system" { - fn AddVectoredExceptionHandler(FirstHandler: ULONG, - VectoredHandler: PVECTORED_EXCEPTION_HANDLER) - -> LPVOID; -} +pub unsafe fn cleanup() {} diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 15df5d756be..a9d094375b2 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -11,14 +11,12 @@ use prelude::v1::*; use alloc::boxed::FnBox; -use cmp; use io; use libc::{self, c_void, DWORD}; use mem; use ptr; use sys::c; use sys::handle::Handle; -use sys_common::stack::RED_ZONE; use sys_common::thread::*; use time::Duration; @@ -36,11 +34,9 @@ impl Thread { // PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's // just that below a certain threshold you can't do anything useful. // That threshold is application and architecture-specific, however. - // For now, the only requirement is that it's big enough to hold the - // red zone. Round up to the next 64 kB because that's what the NT - // kernel does, might as well make it explicit. With the current - // 20 kB red zone, that makes for a 64 kB minimum stack. - let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1); + // Round up to the next 64 kB because that's what the NT kernel does, + // might as well make it explicit. + let stack_size = (stack + 0xfffe) & (!0xfffe); let ret = c::CreateThread(ptr::null_mut(), stack_size as libc::size_t, thread_start, &*p as *const _ as *mut _, 0, ptr::null_mut()); @@ -52,7 +48,6 @@ impl Thread { Ok(Thread { handle: Handle::new(ret) }) }; - #[no_stack_check] extern "system" fn thread_start(main: *mut libc::c_void) -> DWORD { unsafe { start_thread(main); } 0 |
