diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 2746f87468dca..57ec0005bf428 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -1,6 +1,7 @@ use crate::convert::TryInto; use crate::fmt; use crate::io::{self, Error, ErrorKind}; +use crate::panic; use crate::ptr; use crate::sys; use crate::sys::cvt; @@ -53,7 +54,7 @@ impl Command { let pid = unsafe { match result { - 0 => { + 0 => match panic::catch_unwind(panic::AssertUnwindSafe(|| -> ! { drop(input); let Err(err) = self.do_exec(theirs, envp.as_ref()); let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; @@ -73,7 +74,9 @@ impl Command { // we're being torn down regardless rtassert!(output.write(&bytes).is_ok()); libc::_exit(1) - } + })) { + Err(_) => crate::process::abort(), + }, n => n, } }; @@ -533,3 +536,7 @@ impl fmt::Display for ExitStatus { } } } + +#[cfg(test)] +#[path = "process_unix/tests.rs"] +mod tests; diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs new file mode 100644 index 0000000000000..9be1deea673c5 --- /dev/null +++ b/library/std/src/sys/unix/process/process_unix/tests.rs @@ -0,0 +1,22 @@ +#[test] +fn test_command_fork_no_unwind() { + use crate::os::unix::process::CommandExt; + use crate::os::unix::process::ExitStatusExt; + use crate::panic::catch_unwind; + use crate::process::Command; + + 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"); + eprintln!("{:?}", st); + st + }); + eprintln!("got={:?}", &got); + let estatus = got.expect("panic unexpectedly propagated"); + let signal = estatus.signal().expect("expected child to die of signal"); + assert!(signal == libc::SIGABRT || signal == libc::SIGILL); +}