Skip to content

Commit a6b8c69

Browse files
committed
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
2 parents 7e9b92c + 22791bb commit a6b8c69

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

Diff for: library/std/src/sys/unix/process/process_unix.rs

+79-3
Original file line numberDiff line numberDiff line change
@@ -695,18 +695,94 @@ impl From<c_int> for ExitStatus {
695695
}
696696
}
697697

698+
/// Convert a signal number to a readable, searchable name.
699+
///
700+
/// This string should be displayed right after the signal number.
701+
/// If a signal is unrecognized, it returns the empty string, so that
702+
/// you just get the number like "0". If it is recognized, you'll get
703+
/// something like "9 (SIGKILL)".
704+
fn signal_string(signal: i32) -> &'static str {
705+
match signal {
706+
libc::SIGHUP => " (SIGHUP)",
707+
libc::SIGINT => " (SIGINT)",
708+
libc::SIGQUIT => " (SIGQUIT)",
709+
libc::SIGILL => " (SIGILL)",
710+
libc::SIGTRAP => " (SIGTRAP)",
711+
libc::SIGABRT => " (SIGABRT)",
712+
libc::SIGBUS => " (SIGBUS)",
713+
libc::SIGFPE => " (SIGFPE)",
714+
libc::SIGKILL => " (SIGKILL)",
715+
libc::SIGUSR1 => " (SIGUSR1)",
716+
libc::SIGSEGV => " (SIGSEGV)",
717+
libc::SIGUSR2 => " (SIGUSR2)",
718+
libc::SIGPIPE => " (SIGPIPE)",
719+
libc::SIGALRM => " (SIGALRM)",
720+
libc::SIGTERM => " (SIGTERM)",
721+
libc::SIGCHLD => " (SIGCHLD)",
722+
libc::SIGCONT => " (SIGCONT)",
723+
libc::SIGSTOP => " (SIGSTOP)",
724+
libc::SIGTSTP => " (SIGTSTP)",
725+
libc::SIGTTIN => " (SIGTTIN)",
726+
libc::SIGTTOU => " (SIGTTOU)",
727+
libc::SIGURG => " (SIGURG)",
728+
libc::SIGXCPU => " (SIGXCPU)",
729+
libc::SIGXFSZ => " (SIGXFSZ)",
730+
libc::SIGVTALRM => " (SIGVTALRM)",
731+
libc::SIGPROF => " (SIGPROF)",
732+
libc::SIGWINCH => " (SIGWINCH)",
733+
libc::SIGIO => " (SIGIO)",
734+
libc::SIGSYS => " (SIGSYS)",
735+
// For information on Linux signals, run `man 7 signal`
736+
#[cfg(all(
737+
target_os = "linux",
738+
any(
739+
target_arch = "x86_64",
740+
target_arch = "x86",
741+
target_arch = "arm",
742+
target_arch = "aarch64"
743+
)
744+
))]
745+
libc::SIGSTKFLT => " (SIGSTKFLT)",
746+
#[cfg(target_os = "linux")]
747+
libc::SIGPWR => " (SIGPWR)",
748+
#[cfg(any(
749+
target_os = "macos",
750+
target_os = "ios",
751+
target_os = "tvos",
752+
target_os = "freebsd",
753+
target_os = "netbsd",
754+
target_os = "openbsd",
755+
target_os = "dragonfly"
756+
))]
757+
libc::SIGEMT => " (SIGEMT)",
758+
#[cfg(any(
759+
target_os = "macos",
760+
target_os = "ios",
761+
target_os = "tvos",
762+
target_os = "freebsd",
763+
target_os = "netbsd",
764+
target_os = "openbsd",
765+
target_os = "dragonfly"
766+
))]
767+
libc::SIGINFO => " (SIGINFO)",
768+
_ => "",
769+
}
770+
}
771+
698772
impl fmt::Display for ExitStatus {
699773
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
700774
if let Some(code) = self.code() {
701775
write!(f, "exit status: {code}")
702776
} else if let Some(signal) = self.signal() {
777+
let signal_string = signal_string(signal);
703778
if self.core_dumped() {
704-
write!(f, "signal: {signal} (core dumped)")
779+
write!(f, "signal: {signal}{signal_string} (core dumped)")
705780
} else {
706-
write!(f, "signal: {signal}")
781+
write!(f, "signal: {signal}{signal_string}")
707782
}
708783
} else if let Some(signal) = self.stopped_signal() {
709-
write!(f, "stopped (not terminated) by signal: {signal}")
784+
let signal_string = signal_string(signal);
785+
write!(f, "stopped (not terminated) by signal: {signal}{signal_string}")
710786
} else if self.continued() {
711787
write!(f, "continued (WIFCONTINUED)")
712788
} else {

Diff for: library/std/src/sys/unix/process/process_unix/tests.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ fn exitstatus_display_tests() {
1414

1515
let t = |v, s| assert_eq!(s, format!("{}", <ExitStatus as ExitStatusExt>::from_raw(v)));
1616

17-
t(0x0000f, "signal: 15");
18-
t(0x0008b, "signal: 11 (core dumped)");
17+
t(0x0000f, "signal: 15 (SIGTERM)");
18+
t(0x0008b, "signal: 11 (SIGSEGV) (core dumped)");
1919
t(0x00000, "exit status: 0");
2020
t(0x0ff00, "exit status: 255");
2121

@@ -24,7 +24,7 @@ fn exitstatus_display_tests() {
2424
// The purpose of this test is to test our string formatting, not our understanding of the wait
2525
// status magic numbers. So restrict these to Linux.
2626
if cfg!(target_os = "linux") {
27-
t(0x0137f, "stopped (not terminated) by signal: 19");
27+
t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)");
2828
t(0x0ffff, "continued (WIFCONTINUED)");
2929
}
3030

0 commit comments

Comments
 (0)