unix_sigpipe: Add test for SIGPIPE disposition in child processes
For robustness, also test the disposition in our own process even if other tests in `tests/ui/attributes/unix_sigpipe` already covers it.
This commit is contained in:
parent
a2a2f30415
commit
71eb763d23
@ -0,0 +1,34 @@
|
||||
// It is UB to unwind out of `fn start()` according to
|
||||
// https://doc.rust-lang.org/beta/unstable-book/language-features/start.html so
|
||||
// panic with abort to avoid UB:
|
||||
//@ compile-flags: -Cpanic=abort
|
||||
//@ no-prefer-dynamic so panic=abort works
|
||||
|
||||
#![feature(start, rustc_private)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
// Use #[start] so we don't have a runtime that messes with SIGPIPE.
|
||||
#[start]
|
||||
fn start(argc: isize, argv: *const *const u8) -> isize {
|
||||
assert_eq!(argc, 2, "Must pass SIG_IGN or SIG_DFL as first arg");
|
||||
let arg1 = unsafe { std::ffi::CStr::from_ptr(*argv.offset(1) as *const libc::c_char) }
|
||||
.to_str()
|
||||
.unwrap();
|
||||
|
||||
let expected = match arg1 {
|
||||
"SIG_IGN" => libc::SIG_IGN,
|
||||
"SIG_DFL" => libc::SIG_DFL,
|
||||
arg => panic!("Must pass SIG_IGN or SIG_DFL as first arg. Got: {}", arg),
|
||||
};
|
||||
|
||||
let actual = unsafe {
|
||||
let mut actual: libc::sigaction = std::mem::zeroed();
|
||||
libc::sigaction(libc::SIGPIPE, std::ptr::null(), &mut actual);
|
||||
actual.sa_sigaction
|
||||
};
|
||||
|
||||
assert_eq!(actual, expected, "actual and expected SIGPIPE disposition in child differs");
|
||||
|
||||
0
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//@ revisions: default sig_dfl sig_ign inherit
|
||||
//@ ignore-cross-compile because aux-bin does not yet support it
|
||||
//@ only-unix because SIGPIPE is a unix thing
|
||||
//@ run-pass
|
||||
//@ aux-bin:assert-sigpipe-disposition.rs
|
||||
//@ aux-crate:sigpipe_utils=sigpipe-utils.rs
|
||||
|
||||
// Checks the signal disposition of `SIGPIPE` in child processes, and in our own
|
||||
// process for robustness. Without any `unix_sigpipe` attribute, `SIG_IGN` is
|
||||
// the default. But there is a difference in how `SIGPIPE` is treated in child
|
||||
// processes with and without the attribute. Search for
|
||||
// `unix_sigpipe_attr_specified()` in the code base to learn more.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![cfg_attr(any(sig_dfl, sig_ign, inherit), feature(unix_sigpipe))]
|
||||
|
||||
extern crate libc;
|
||||
extern crate sigpipe_utils;
|
||||
|
||||
use sigpipe_utils::*;
|
||||
|
||||
#[cfg_attr(sig_dfl, unix_sigpipe = "sig_dfl")]
|
||||
#[cfg_attr(sig_ign, unix_sigpipe = "sig_ign")]
|
||||
#[cfg_attr(inherit, unix_sigpipe = "inherit")]
|
||||
fn main() {
|
||||
// By default we get SIG_IGN but the child gets SIG_DFL through an explicit
|
||||
// reset before exec:
|
||||
// https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L363-L384
|
||||
#[cfg(default)]
|
||||
let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_DFL");
|
||||
|
||||
// With #[unix_sigpipe = "sig_dfl"] we get SIG_DFL and the child does too
|
||||
// without any special code running before exec.
|
||||
#[cfg(sig_dfl)]
|
||||
let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL");
|
||||
|
||||
// With #[unix_sigpipe = "sig_ign"] we get SIG_IGN and the child does too
|
||||
// without any special code running before exec.
|
||||
#[cfg(sig_ign)]
|
||||
let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_IGN");
|
||||
|
||||
// With #[unix_sigpipe = "inherit"] we get SIG_DFL and the child does too
|
||||
// without any special code running before exec.
|
||||
#[cfg(inherit)]
|
||||
let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL");
|
||||
|
||||
assert_sigpipe_handler(we_expect);
|
||||
|
||||
assert!(
|
||||
std::process::Command::new("./auxiliary/bin/assert-sigpipe-disposition")
|
||||
.arg(child_expects)
|
||||
.status()
|
||||
.unwrap()
|
||||
.success()
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user