]> git.lizzy.rs Git - rust.git/blob - tests/ui/panics/abort-on-panic.rs
Rollup merge of #106726 - cmorin6:fix-comment-typos, r=Nilstrieb
[rust.git] / tests / ui / panics / abort-on-panic.rs
1 // run-pass
2
3 #![allow(unused_must_use)]
4 #![feature(c_unwind)]
5 #![feature(panic_always_abort)]
6 // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
7 // we never unwind through them.
8
9 // ignore-emscripten no processes
10 // ignore-sgx no processes
11
12 use std::io;
13 use std::io::prelude::*;
14 use std::process::{exit, Command, Stdio};
15 use std::sync::{Arc, Barrier};
16 use std::thread;
17 use std::{env, panic};
18
19 extern "C" fn panic_in_ffi() {
20     panic!("Test");
21 }
22
23 fn should_have_aborted() {
24     io::stdout().write(b"This should never be printed.\n");
25     let _ = io::stdout().flush();
26 }
27
28 fn bomb_out_but_not_abort(msg: &str) {
29     eprintln!("bombing out: {}", msg);
30     exit(1);
31 }
32
33 fn test() {
34     let _ = panic::catch_unwind(|| {
35         panic_in_ffi();
36     });
37     should_have_aborted();
38 }
39
40 fn test_always_abort() {
41     panic::always_abort();
42     let _ = panic::catch_unwind(|| {
43         panic!();
44     });
45     should_have_aborted();
46 }
47
48 fn test_always_abort_thread() {
49     let barrier = Arc::new(Barrier::new(2));
50     let thr = {
51         let barrier = barrier.clone();
52         thread::spawn(move || {
53             barrier.wait();
54             panic!("in thread");
55         })
56     };
57     panic::always_abort();
58     barrier.wait();
59     let _ = thr.join();
60     bomb_out_but_not_abort("joined - but we were supposed to panic!");
61 }
62
63 fn main() {
64     let tests: &[(_, fn())] = &[
65         ("test", test),
66         ("test_always_abort", test_always_abort),
67         ("test_always_abort_thread", test_always_abort_thread),
68     ];
69
70     let args: Vec<String> = env::args().collect();
71     if args.len() > 1 {
72         // This is inside the self-executed command.
73         for (a, f) in tests {
74             if &args[1] == a {
75                 return f();
76             }
77         }
78         bomb_out_but_not_abort("bad test");
79     }
80
81     let execute_self_expecting_abort = |arg| {
82         let mut p = Command::new(&args[0])
83             .stdout(Stdio::piped())
84             .stdin(Stdio::piped())
85             .arg(arg)
86             .spawn()
87             .unwrap();
88         let status = p.wait().unwrap();
89         assert!(!status.success());
90         // Any reasonable platform can distinguish a process which
91         // called exit(1) from one which panicked.
92         assert_ne!(status.code(), Some(1));
93     };
94
95     for (a, _f) in tests {
96         execute_self_expecting_abort(a);
97     }
98 }