1#![cfg(unix)]
2
3#[test]
4fn crash_child() {
5 let Some(path) = std::env::var_os("SNOWBOUND_TEST_CRASH") else {
6 return;
7 };
8 crash_report::hook("test", "native-test".into(), "test system".into(), |_| {});
9 crash_report::set_path(path.into()).unwrap();
10 #[cfg(target_os = "linux")]
11 {
12 extern "C" fn fatal(signal: i32, info: *mut libc::siginfo_t, _: *mut libc::c_void) {
13 unsafe {
14 crash_report::record_signal(signal, info);
15 libc::raise(signal);
16 }
17 }
18 let mut action: libc::sigaction = unsafe { std::mem::zeroed() };
19 action.sa_sigaction = fatal as *const () as libc::sighandler_t;
20 action.sa_flags = libc::SA_SIGINFO | libc::SA_RESETHAND;
21 unsafe {
22 libc::sigaction(libc::SIGABRT, &action, std::ptr::null_mut());
23 }
24 }
25 if std::env::var_os("SNOWBOUND_TEST_PANIC").is_some() {
26 crash_report::conceal("AI.one");
27 let _ = std::panic::catch_unwind(|| panic!("Cannot read section AI"));
28 }
29 std::process::abort();
30}
31
32#[test]
33fn fatal_signals_leave_a_report_and_preserve_the_first_panic() {
34 use std::{
35 os::unix::process::ExitStatusExt,
36 process::{Command, Stdio},
37 };
38 let folder = tempfile::tempdir().unwrap();
39 for panic in [false, true] {
40 let report = folder
41 .path()
42 .join(if panic { "panic.txt" } else { "native.txt" });
43 let mut child = Command::new(std::env::current_exe().unwrap());
44 child
45 .args(["--exact", "crash_child", "--nocapture"])
46 .env("SNOWBOUND_TEST_CRASH", &report)
47 .stdout(Stdio::null())
48 .stderr(Stdio::null());
49 if panic {
50 child.env("SNOWBOUND_TEST_PANIC", "1");
51 }
52 assert_eq!(child.status().unwrap().signal(), Some(libc::SIGABRT));
53 let saved = std::fs::read_to_string(report).unwrap();
54 assert!(
55 saved.starts_with("Snowbound test, native-test\nSystem: test system\n"),
56 "{saved}"
57 );
58 if panic {
59 assert!(
60 saved.contains("Panic: Cannot read section <name>"),
61 "{saved}"
62 );
63 assert!(!saved.contains("Native signal"), "{saved}");
64 } else {
65 assert!(saved.contains("Native signal:"), "{saved}");
66 assert!(!saved.contains("Fault address:"), "{saved}");
67 }
68 }
69}