lib.rs
1 //! Explain a wait status. 2 //! 3 //! A wait status is returned by one of the `wait` family of system 4 //! calls. It contains the exit code (given to the `_exit` system 5 //! call), but also other information. 6 //! 7 //! This crate, or its tests, may be Linux specific. 8 9 use serde::Serialize; 10 11 /// Explained wait status. 12 #[derive(Debug, Serialize)] 13 pub struct Explained { 14 /// The wait status given to [`Explained::new`]. 15 pub wait_status: i32, 16 17 /// Did the process exit normally? (If not, it may be running, or 18 /// was terminated by a signal.) 19 pub exited: bool, 20 21 /// Exit status code, if `exited` is true. 22 pub exit_status: Option<i32>, 23 24 /// Was the process terminated by signal? 25 pub signaled: bool, 26 27 /// If `signaled` is `true`, what signal? 28 pub termsig: Option<i32>, 29 30 /// If `signaled` is `true`, did process produce a core dump? 31 pub coredump: bool, 32 33 /// Was the process stopped by a signal? 34 pub stopped: bool, 35 36 /// If `stopped` is `true`, what signal? 37 pub stopsig: Option<i32>, 38 39 /// Was stopped process resumed by signal **SIGCONT**? 40 pub continued: bool, 41 } 42 43 impl Explained { 44 pub fn new(wait_status: i32) -> Self { 45 let exited = libc::WIFEXITED(wait_status); 46 let signaled = libc::WIFSIGNALED(wait_status); 47 let stopped = libc::WIFSTOPPED(wait_status); 48 49 Self { 50 wait_status, 51 exited, 52 exit_status: if exited { 53 Some(libc::WEXITSTATUS(wait_status)) 54 } else { 55 None 56 }, 57 signaled, 58 termsig: if signaled { 59 Some(libc::WTERMSIG(wait_status)) 60 } else { 61 None 62 }, 63 coredump: signaled && libc::WCOREDUMP(wait_status), 64 stopped, 65 stopsig: if stopped { 66 Some(libc::WSTOPSIG(wait_status)) 67 } else { 68 None 69 }, 70 continued: libc::WIFCONTINUED(wait_status), 71 } 72 } 73 } 74 75 #[cfg(test)] 76 mod test { 77 use super::*; 78 79 #[test] 80 fn normal_exits() { 81 for i in 0..255 { 82 // On Linux, for normal exit codes, wait status is shifted by 8 bits. 83 let wait_status = i << 8; 84 let ex = Explained::new(wait_status); 85 86 // Print the result to help debug test failures. 87 println!("{i} => {ex:#?}"); 88 89 assert_eq!(ex.wait_status, wait_status); 90 assert!(ex.exited); 91 assert_eq!(ex.exit_status, Some(i)); 92 assert!(!ex.signaled); 93 assert_eq!(ex.termsig, None); 94 assert!(!ex.coredump); 95 assert!(!ex.stopped); 96 assert_eq!(ex.stopsig, None); 97 assert!(!ex.continued); 98 } 99 } 100 }