2021-02-07 11:42:44 +00:00
|
|
|
use crate::os::unix::process::{CommandExt, ExitStatusExt};
|
|
|
|
use crate::panic::catch_unwind;
|
|
|
|
use crate::process::Command;
|
|
|
|
|
2021-02-07 12:16:11 +00:00
|
|
|
// Many of the other aspects of this situation, including heap alloc concurrency
|
2023-01-05 09:45:44 +01:00
|
|
|
// safety etc., are tested in tests/ui/process/process-panic-after-fork.rs
|
2021-02-07 12:16:11 +00:00
|
|
|
|
2021-02-22 14:58:52 +00:00
|
|
|
#[test]
|
|
|
|
fn exitstatus_display_tests() {
|
|
|
|
// In practice this is the same on every Unix.
|
|
|
|
// If some weird platform turns out to be different, and this test fails, use #[cfg].
|
|
|
|
use crate::os::unix::process::ExitStatusExt;
|
|
|
|
use crate::process::ExitStatus;
|
|
|
|
|
|
|
|
let t = |v, s| assert_eq!(s, format!("{}", <ExitStatus as ExitStatusExt>::from_raw(v)));
|
|
|
|
|
2022-06-01 11:20:11 -07:00
|
|
|
t(0x0000f, "signal: 15 (SIGTERM)");
|
|
|
|
t(0x0008b, "signal: 11 (SIGSEGV) (core dumped)");
|
ExitStatus: print "exit status: {}" rather than "exit code: {}"
Proper Unix terminology is "exit status" (vs "wait status"). "exit
code" is imprecise on Unix and therefore unclear. (As far as I can
tell, "exit code" is correct terminology on Windows.)
This new wording is unfortunately inconsistent with the identifier
names in the Rust stdlib.
It is the identifier names that are wrong, as discussed at length in eg
https://doc.rust-lang.org/nightly/std/process/struct.ExitStatus.html
https://doc.rust-lang.org/nightly/std/os/unix/process/trait.ExitStatusExt.html
Unfortunately for API stability reasons it would be a lot of work, and
a lot of disruption, to change the names in the stdlib (eg to rename
`std::process::ExitStatus` to `std::process::ChildStatus` or
something), but we should fix the message output. Many (probably
most) readers of these messages about exit statuses will be users and
system administrators, not programmers, who won't even know that Rust
has this wrong terminology.
So I think the right thing is to fix the documentation (as I have
already done) and, now, the terminology in the implementation.
This is a user-visible change to the behaviour of all Rust programs
which run Unix subprocesses. Hopefully no-one is matching against the
exit status string, except perhaps in tests.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-03-25 10:27:53 +00:00
|
|
|
t(0x00000, "exit status: 0");
|
|
|
|
t(0x0ff00, "exit status: 255");
|
2021-03-04 12:18:04 +00:00
|
|
|
|
|
|
|
// On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED. Probably *BSD is similar.
|
|
|
|
// https://github.com/rust-lang/rust/pull/82749#issuecomment-790525956
|
|
|
|
// 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.
|
2021-03-09 10:53:03 +00:00
|
|
|
if cfg!(target_os = "linux") {
|
2022-06-01 11:20:11 -07:00
|
|
|
t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)");
|
2021-03-09 10:53:03 +00:00
|
|
|
t(0x0ffff, "continued (WIFCONTINUED)");
|
|
|
|
}
|
2021-02-22 14:58:52 +00:00
|
|
|
|
|
|
|
// Testing "unrecognised wait status" is hard because the wait.h macros typically
|
|
|
|
// assume that the value came from wait and isn't mad. With the glibc I have here
|
|
|
|
// this works:
|
2021-03-09 10:53:03 +00:00
|
|
|
if cfg!(all(target_os = "linux", target_env = "gnu")) {
|
|
|
|
t(0x000ff, "unrecognised wait status: 255 0xff");
|
|
|
|
}
|
2021-02-22 14:58:52 +00:00
|
|
|
}
|
2021-02-07 11:42:44 +00:00
|
|
|
|
|
|
|
#[test]
|
2021-05-07 16:15:53 +01:00
|
|
|
#[cfg_attr(target_os = "emscripten", ignore)]
|
2021-02-07 11:42:44 +00:00
|
|
|
fn test_command_fork_no_unwind() {
|
|
|
|
let got = catch_unwind(|| {
|
|
|
|
let mut c = Command::new("echo");
|
|
|
|
c.arg("hi");
|
|
|
|
unsafe {
|
|
|
|
c.pre_exec(|| panic!("{}", "crash now!"));
|
|
|
|
}
|
|
|
|
let st = c.status().expect("failed to get command status");
|
|
|
|
dbg!(st);
|
|
|
|
st
|
|
|
|
});
|
|
|
|
dbg!(&got);
|
|
|
|
let status = got.expect("panic unexpectedly propagated");
|
|
|
|
dbg!(status);
|
|
|
|
let signal = status.signal().expect("expected child process to die of signal");
|
2022-01-21 15:44:57 +00:00
|
|
|
assert!(
|
|
|
|
signal == libc::SIGABRT
|
|
|
|
|| signal == libc::SIGILL
|
|
|
|
|| signal == libc::SIGTRAP
|
|
|
|
|| signal == libc::SIGSEGV
|
|
|
|
);
|
2021-02-07 11:42:44 +00:00
|
|
|
}
|