Auto merge of #95833 - notriddle:notriddle/human-readable-signals, r=yaahc
std: `<ExitStatus as Display>::fmt` name the signal it died from Related to #95601
This commit is contained in:
commit
a6b8c69548
2 changed files with 82 additions and 6 deletions
|
@ -695,18 +695,94 @@ impl From<c_int> for ExitStatus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert a signal number to a readable, searchable name.
|
||||||
|
///
|
||||||
|
/// This string should be displayed right after the signal number.
|
||||||
|
/// If a signal is unrecognized, it returns the empty string, so that
|
||||||
|
/// you just get the number like "0". If it is recognized, you'll get
|
||||||
|
/// something like "9 (SIGKILL)".
|
||||||
|
fn signal_string(signal: i32) -> &'static str {
|
||||||
|
match signal {
|
||||||
|
libc::SIGHUP => " (SIGHUP)",
|
||||||
|
libc::SIGINT => " (SIGINT)",
|
||||||
|
libc::SIGQUIT => " (SIGQUIT)",
|
||||||
|
libc::SIGILL => " (SIGILL)",
|
||||||
|
libc::SIGTRAP => " (SIGTRAP)",
|
||||||
|
libc::SIGABRT => " (SIGABRT)",
|
||||||
|
libc::SIGBUS => " (SIGBUS)",
|
||||||
|
libc::SIGFPE => " (SIGFPE)",
|
||||||
|
libc::SIGKILL => " (SIGKILL)",
|
||||||
|
libc::SIGUSR1 => " (SIGUSR1)",
|
||||||
|
libc::SIGSEGV => " (SIGSEGV)",
|
||||||
|
libc::SIGUSR2 => " (SIGUSR2)",
|
||||||
|
libc::SIGPIPE => " (SIGPIPE)",
|
||||||
|
libc::SIGALRM => " (SIGALRM)",
|
||||||
|
libc::SIGTERM => " (SIGTERM)",
|
||||||
|
libc::SIGCHLD => " (SIGCHLD)",
|
||||||
|
libc::SIGCONT => " (SIGCONT)",
|
||||||
|
libc::SIGSTOP => " (SIGSTOP)",
|
||||||
|
libc::SIGTSTP => " (SIGTSTP)",
|
||||||
|
libc::SIGTTIN => " (SIGTTIN)",
|
||||||
|
libc::SIGTTOU => " (SIGTTOU)",
|
||||||
|
libc::SIGURG => " (SIGURG)",
|
||||||
|
libc::SIGXCPU => " (SIGXCPU)",
|
||||||
|
libc::SIGXFSZ => " (SIGXFSZ)",
|
||||||
|
libc::SIGVTALRM => " (SIGVTALRM)",
|
||||||
|
libc::SIGPROF => " (SIGPROF)",
|
||||||
|
libc::SIGWINCH => " (SIGWINCH)",
|
||||||
|
libc::SIGIO => " (SIGIO)",
|
||||||
|
libc::SIGSYS => " (SIGSYS)",
|
||||||
|
// For information on Linux signals, run `man 7 signal`
|
||||||
|
#[cfg(all(
|
||||||
|
target_os = "linux",
|
||||||
|
any(
|
||||||
|
target_arch = "x86_64",
|
||||||
|
target_arch = "x86",
|
||||||
|
target_arch = "arm",
|
||||||
|
target_arch = "aarch64"
|
||||||
|
)
|
||||||
|
))]
|
||||||
|
libc::SIGSTKFLT => " (SIGSTKFLT)",
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
libc::SIGPWR => " (SIGPWR)",
|
||||||
|
#[cfg(any(
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "ios",
|
||||||
|
target_os = "tvos",
|
||||||
|
target_os = "freebsd",
|
||||||
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
target_os = "dragonfly"
|
||||||
|
))]
|
||||||
|
libc::SIGEMT => " (SIGEMT)",
|
||||||
|
#[cfg(any(
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "ios",
|
||||||
|
target_os = "tvos",
|
||||||
|
target_os = "freebsd",
|
||||||
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
target_os = "dragonfly"
|
||||||
|
))]
|
||||||
|
libc::SIGINFO => " (SIGINFO)",
|
||||||
|
_ => "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for ExitStatus {
|
impl fmt::Display for ExitStatus {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if let Some(code) = self.code() {
|
if let Some(code) = self.code() {
|
||||||
write!(f, "exit status: {code}")
|
write!(f, "exit status: {code}")
|
||||||
} else if let Some(signal) = self.signal() {
|
} else if let Some(signal) = self.signal() {
|
||||||
|
let signal_string = signal_string(signal);
|
||||||
if self.core_dumped() {
|
if self.core_dumped() {
|
||||||
write!(f, "signal: {signal} (core dumped)")
|
write!(f, "signal: {signal}{signal_string} (core dumped)")
|
||||||
} else {
|
} else {
|
||||||
write!(f, "signal: {signal}")
|
write!(f, "signal: {signal}{signal_string}")
|
||||||
}
|
}
|
||||||
} else if let Some(signal) = self.stopped_signal() {
|
} else if let Some(signal) = self.stopped_signal() {
|
||||||
write!(f, "stopped (not terminated) by signal: {signal}")
|
let signal_string = signal_string(signal);
|
||||||
|
write!(f, "stopped (not terminated) by signal: {signal}{signal_string}")
|
||||||
} else if self.continued() {
|
} else if self.continued() {
|
||||||
write!(f, "continued (WIFCONTINUED)")
|
write!(f, "continued (WIFCONTINUED)")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,8 +14,8 @@ fn exitstatus_display_tests() {
|
||||||
|
|
||||||
let t = |v, s| assert_eq!(s, format!("{}", <ExitStatus as ExitStatusExt>::from_raw(v)));
|
let t = |v, s| assert_eq!(s, format!("{}", <ExitStatus as ExitStatusExt>::from_raw(v)));
|
||||||
|
|
||||||
t(0x0000f, "signal: 15");
|
t(0x0000f, "signal: 15 (SIGTERM)");
|
||||||
t(0x0008b, "signal: 11 (core dumped)");
|
t(0x0008b, "signal: 11 (SIGSEGV) (core dumped)");
|
||||||
t(0x00000, "exit status: 0");
|
t(0x00000, "exit status: 0");
|
||||||
t(0x0ff00, "exit status: 255");
|
t(0x0ff00, "exit status: 255");
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ fn exitstatus_display_tests() {
|
||||||
// The purpose of this test is to test our string formatting, not our understanding of the wait
|
// The purpose of this test is to test our string formatting, not our understanding of the wait
|
||||||
// status magic numbers. So restrict these to Linux.
|
// status magic numbers. So restrict these to Linux.
|
||||||
if cfg!(target_os = "linux") {
|
if cfg!(target_os = "linux") {
|
||||||
t(0x0137f, "stopped (not terminated) by signal: 19");
|
t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)");
|
||||||
t(0x0ffff, "continued (WIFCONTINUED)");
|
t(0x0ffff, "continued (WIFCONTINUED)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue