3 #![allow(unused_must_use)]
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.
9 // ignore-emscripten no processes
10 // ignore-sgx no processes
13 use std::io::prelude::*;
14 use std::process::{exit, Command, Stdio};
15 use std::sync::{Arc, Barrier};
17 use std::{env, panic};
19 extern "C" fn panic_in_ffi() {
23 fn should_have_aborted() {
24 io::stdout().write(b"This should never be printed.\n");
25 let _ = io::stdout().flush();
28 fn bomb_out_but_not_abort(msg: &str) {
29 eprintln!("bombing out: {}", msg);
34 let _ = panic::catch_unwind(|| {
37 should_have_aborted();
40 fn test_always_abort() {
41 panic::always_abort();
42 let _ = panic::catch_unwind(|| {
45 should_have_aborted();
48 fn test_always_abort_thread() {
49 let barrier = Arc::new(Barrier::new(2));
51 let barrier = barrier.clone();
52 thread::spawn(move || {
57 panic::always_abort();
60 bomb_out_but_not_abort("joined - but we were supposed to panic!");
64 let tests: &[(_, fn())] = &[
66 ("test_always_abort", test_always_abort),
67 ("test_always_abort_thread", test_always_abort_thread),
70 let args: Vec<String> = env::args().collect();
72 // This is inside the self-executed command.
78 bomb_out_but_not_abort("bad test");
81 let execute_self_expecting_abort = |arg| {
82 let mut p = Command::new(&args[0])
83 .stdout(Stdio::piped())
84 .stdin(Stdio::piped())
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));
95 for (a, _f) in tests {
96 execute_self_expecting_abort(a);