diff options
| author | bors <bors@rust-lang.org> | 2025-03-22 20:52:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-03-22 20:52:30 +0000 |
| commit | b48576b4db5a595f453891f0b7243ef75d8c0afa (patch) | |
| tree | e9d3a1a7b8b1d4182a343702d45abc844ce7b846 /library/std/src/sys/pal/unix/stack_overflow.rs | |
| parent | d93f678fa55842cccd2f091deccd93e9494b3764 (diff) | |
| parent | 2644500bff498ddbb2d1237c4ee43af2ef60a084 (diff) | |
| download | rust-b48576b4db5a595f453891f0b7243ef75d8c0afa.tar.gz rust-b48576b4db5a595f453891f0b7243ef75d8c0afa.zip | |
Auto merge of #138831 - matthiaskrgr:rollup-3t0dqiz, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #138609 (Add stack overflow handler for cygwin) - #138639 (Clean UI tests 2 of n) - #138773 (catch_unwind intrinsic: document return value) - #138782 (test(ui): add tuple-struct-where-clause-suggestion ui test for #91520) - #138794 (expand: Do not report `cfg_attr` traces on macros as unused attributes) - #138801 (triagebot: add autolabel rules for D-* and L-*) - #138804 (Allow inlining for `Atomic*::from_ptr`) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'library/std/src/sys/pal/unix/stack_overflow.rs')
| -rw-r--r-- | library/std/src/sys/pal/unix/stack_overflow.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 0ecccdc8812..4bd0cedd44c 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -585,6 +585,7 @@ mod imp { target_os = "openbsd", target_os = "solaris", target_os = "illumos", + target_os = "cygwin", )))] mod imp { pub unsafe fn init() {} @@ -597,3 +598,89 @@ mod imp { pub unsafe fn drop_handler(_data: *mut libc::c_void) {} } + +#[cfg(target_os = "cygwin")] +mod imp { + mod c { + pub type PVECTORED_EXCEPTION_HANDLER = + Option<unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32>; + pub type NTSTATUS = i32; + pub type BOOL = i32; + + unsafe extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut core::ffi::c_void; + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; + } + + pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; + + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + // We don't need this field here + // pub Context: *mut CONTEXT, + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], + } + } + + /// Reserve stack space for use in stack overflow exceptions. + fn reserve_stack() { + let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; + // Reserving stack space is not critical so we allow it to fail in the released build of libstd. + // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. + debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); + } + + unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { + // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. + unsafe { + let rec = &(*(*ExceptionInfo).ExceptionRecord); + let code = rec.ExceptionCode; + + if code == c::EXCEPTION_STACK_OVERFLOW { + crate::thread::with_current_name(|name| { + let name = name.unwrap_or("<unknown>"); + rtprintpanic!("\nthread '{name}' has overflowed its stack\n"); + }); + } + c::EXCEPTION_CONTINUE_SEARCH + } + } + + pub unsafe fn init() { + // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. + unsafe { + let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); + // Similar to the above, adding the stack overflow handler is allowed to fail + // but a debug assert is used so CI will still test that it normally works. + debug_assert!(!result.is_null(), "failed to install exception handler"); + } + // Set the thread stack guarantee for the main thread. + reserve_stack(); + } + + pub unsafe fn cleanup() {} + + pub unsafe fn make_handler(main_thread: bool) -> super::Handler { + if !main_thread { + reserve_stack(); + } + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} |
