• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)9 fn 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()17 fn 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>30 fn overflow_code() -> Option<i32> {
31     None
32 }
33 
34 #[cfg(windows)]
overflow_code() -> Option<i32>35 fn 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()42 fn 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