std/sys/pal/unix/stack_overflow/mod.rs
1#![cfg_attr(test, allow(dead_code))]
2#![forbid(unsafe_op_in_unsafe_fn)]
3
4cfg_select! {
5 // This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses
6 // several symbols that might lead to rejections from the App Store, namely
7 // `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`.
8 //
9 // This might be overly cautious, though it is also what Swift does (and they
10 // usually have fewer qualms about forwards compatibility, since the runtime
11 // is shipped with the OS):
12 // <https://github.com/apple/swift/blob/swift-5.10-RELEASE/stdlib/public/runtime/CrashHandlerMacOS.cpp>
13 any(
14 target_os = "linux",
15 target_os = "freebsd",
16 target_os = "hurd",
17 target_os = "macos",
18 target_os = "netbsd",
19 target_os = "openbsd",
20 target_os = "solaris",
21 target_os = "illumos",
22 ) => {
23 mod handler_signal;
24 mod thread_info;
25 use handler_signal as imp;
26 }
27 target_os = "cygwin" => {
28 mod handler_cygwin;
29 use handler_cygwin as imp;
30 }
31 _ => {
32 mod handler_none;
33 use handler_none as imp;
34 }
35}
36
37/// # Safety
38/// Must be called only once, on the main thread, during program startup.
39pub unsafe fn init() {
40 // miri doesn't model signals nor stack overflows and this code has some
41 // synchronization properties that we don't want to expose to user code,
42 // hence we disable it on miri.
43 if cfg!(miri) {
44 return;
45 }
46
47 // SAFETY: guaranteed by caller.
48 unsafe { imp::init() };
49}
50
51pub struct Handler {
52 data: *mut libc::c_void,
53}
54
55impl Handler {
56 pub unsafe fn new() -> Handler {
57 // The stack overflow detection logic, even if disabled, has some
58 // synchronization logic that should be disabled under miri.
59 if cfg!(miri) {
60 return Handler::null();
61 }
62
63 imp::make_handler(false)
64 }
65
66 fn null() -> Handler {
67 Handler { data: crate::ptr::null_mut() }
68 }
69}
70
71impl Drop for Handler {
72 fn drop(&mut self) {
73 // The stack overflow detection logic, even if disabled, has some
74 // synchronization logic that should be disabled under miri.
75 if cfg!(miri) {
76 return;
77 }
78
79 unsafe { imp::drop_handler(self.data) };
80 }
81}