1 use std::env;
2 use std::panic;
3 use std::process::Command;
4 use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
5 use std::sync::Arc;
6 use std::thread;
7 
8 const PANICS: usize = 100;
9 const THREADS: usize = 8;
10 const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
11 
12 fn main() {
13     // These run in docker containers on CI where they can't re-exec the test,
14     // so just skip these for CI. No other reason this can't run on those
15     // platforms though.
16     // Miri does not have support for re-execing a file
17     if cfg!(unix)
18         && (cfg!(target_arch = "arm")
19             || cfg!(target_arch = "aarch64")
20             || cfg!(target_arch = "s390x"))
21         || cfg!(miri)
22     {
23         println!("test result: ok");
24         return;
25     }
26 
27     if env::var(VAR).is_err() {
28         parent();
29     } else {
30         child();
31     }
32 }
33 
34 fn parent() {
35     let me = env::current_exe().unwrap();
36     let result = Command::new(&me)
37         .env("RUST_BACKTRACE", "1")
38         .env(VAR, "1")
39         .output()
40         .unwrap();
41     if result.status.success() {
42         println!("test result: ok");
43         return;
44     }
45     println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout));
46     println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr));
47     println!("code: {}", result.status);
48     panic!();
49 }
50 
51 fn child() {
52     let done = Arc::new(AtomicBool::new(false));
53     let done2 = done.clone();
54     let a = thread::spawn(move || {
55         while !done2.load(SeqCst) {
56             format!("{:?}", backtrace::Backtrace::new());
57         }
58     });
59 
60     let threads = (0..THREADS)
61         .map(|_| {
62             thread::spawn(|| {
63                 for _ in 0..PANICS {
64                     assert!(panic::catch_unwind(|| {
65                         panic!();
66                     })
67                     .is_err());
68                 }
69             })
70         })
71         .collect::<Vec<_>>();
72     for thread in threads {
73         thread.join().unwrap();
74     }
75 
76     done.store(true, SeqCst);
77     a.join().unwrap();
78 }
79