1 use rayon_core::ThreadPoolBuilder; 2 3 use std::env; 4 use std::process::Command; 5 6 #[cfg(target_os = "linux")] 7 use std::os::unix::process::ExitStatusExt; 8 force_stack_overflow(depth: u32)9fn force_stack_overflow(depth: u32) { 10 let _buffer = [0u8; 1024 * 1024]; 11 if depth > 0 { 12 force_stack_overflow(depth - 1); 13 } 14 } 15 16 #[cfg(unix)] disable_core()17fn disable_core() { 18 unsafe { 19 libc::setrlimit( 20 libc::RLIMIT_CORE, 21 &libc::rlimit { 22 rlim_cur: 0, 23 rlim_max: 0, 24 }, 25 ); 26 } 27 } 28 29 #[cfg(unix)] overflow_code() -> Option<i32>30fn overflow_code() -> Option<i32> { 31 None 32 } 33 34 #[cfg(windows)] overflow_code() -> Option<i32>35fn overflow_code() -> Option<i32> { 36 use std::os::windows::process::ExitStatusExt; 37 use std::process::ExitStatus; 38 39 ExitStatus::from_raw(0xc00000fd /*STATUS_STACK_OVERFLOW*/).code() 40 } 41 main()42fn main() { 43 if env::args().len() == 1 { 44 // first check that the recursivecall actually causes a stack overflow, and does not get optimized away 45 { 46 let status = Command::new(env::current_exe().unwrap()) 47 .arg("8") 48 .status() 49 .unwrap(); 50 51 #[cfg(any(unix, windows))] 52 assert_eq!(status.code(), overflow_code()); 53 54 #[cfg(target_os = "linux")] 55 assert!( 56 status.signal() == Some(11 /*SIGABRT*/) || status.signal() == Some(6 /*SIGSEGV*/) 57 ); 58 } 59 60 // now run with a larger stack and verify correct operation 61 { 62 let status = Command::new(env::current_exe().unwrap()) 63 .arg("48") 64 .status() 65 .unwrap(); 66 assert_eq!(status.code(), Some(0)); 67 #[cfg(target_os = "linux")] 68 assert_eq!(status.signal(), None); 69 } 70 } else { 71 let stack_size_in_mb: usize = env::args().nth(1).unwrap().parse().unwrap(); 72 let pool = ThreadPoolBuilder::new() 73 .stack_size(stack_size_in_mb * 1024 * 1024) 74 .build() 75 .unwrap(); 76 pool.install(|| { 77 #[cfg(unix)] 78 disable_core(); 79 force_stack_overflow(32); 80 }); 81 } 82 } 83