Skip to content

Commit 017a8ea

Browse files
authored
Rollup merge of rust-lang#121573 - Enselic:sigpipe-child-process, r=Mark-Simulacrum
unix_sigpipe: Add test for SIGPIPE disposition in child processes To make it clearer what the impact would be to stop using `SIG_IGN` and instead use a noop handler, like suggested [here](rust-lang#62569 (comment)) and implemented [here](rust-lang#121578). Part of rust-lang#97889
2 parents 7e0ed43 + 71eb763 commit 017a8ea

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// It is UB to unwind out of `fn start()` according to
2+
// https://doc.rust-lang.org/beta/unstable-book/language-features/start.html so
3+
// panic with abort to avoid UB:
4+
//@ compile-flags: -Cpanic=abort
5+
//@ no-prefer-dynamic so panic=abort works
6+
7+
#![feature(start, rustc_private)]
8+
9+
extern crate libc;
10+
11+
// Use #[start] so we don't have a runtime that messes with SIGPIPE.
12+
#[start]
13+
fn start(argc: isize, argv: *const *const u8) -> isize {
14+
assert_eq!(argc, 2, "Must pass SIG_IGN or SIG_DFL as first arg");
15+
let arg1 = unsafe { std::ffi::CStr::from_ptr(*argv.offset(1) as *const libc::c_char) }
16+
.to_str()
17+
.unwrap();
18+
19+
let expected = match arg1 {
20+
"SIG_IGN" => libc::SIG_IGN,
21+
"SIG_DFL" => libc::SIG_DFL,
22+
arg => panic!("Must pass SIG_IGN or SIG_DFL as first arg. Got: {}", arg),
23+
};
24+
25+
let actual = unsafe {
26+
let mut actual: libc::sigaction = std::mem::zeroed();
27+
libc::sigaction(libc::SIGPIPE, std::ptr::null(), &mut actual);
28+
actual.sa_sigaction
29+
};
30+
31+
assert_eq!(actual, expected, "actual and expected SIGPIPE disposition in child differs");
32+
33+
0
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//@ revisions: default sig_dfl sig_ign inherit
2+
//@ ignore-cross-compile because aux-bin does not yet support it
3+
//@ only-unix because SIGPIPE is a unix thing
4+
//@ run-pass
5+
//@ aux-bin:assert-sigpipe-disposition.rs
6+
//@ aux-crate:sigpipe_utils=sigpipe-utils.rs
7+
8+
// Checks the signal disposition of `SIGPIPE` in child processes, and in our own
9+
// process for robustness. Without any `unix_sigpipe` attribute, `SIG_IGN` is
10+
// the default. But there is a difference in how `SIGPIPE` is treated in child
11+
// processes with and without the attribute. Search for
12+
// `unix_sigpipe_attr_specified()` in the code base to learn more.
13+
14+
#![feature(rustc_private)]
15+
#![cfg_attr(any(sig_dfl, sig_ign, inherit), feature(unix_sigpipe))]
16+
17+
extern crate libc;
18+
extern crate sigpipe_utils;
19+
20+
use sigpipe_utils::*;
21+
22+
#[cfg_attr(sig_dfl, unix_sigpipe = "sig_dfl")]
23+
#[cfg_attr(sig_ign, unix_sigpipe = "sig_ign")]
24+
#[cfg_attr(inherit, unix_sigpipe = "inherit")]
25+
fn main() {
26+
// By default we get SIG_IGN but the child gets SIG_DFL through an explicit
27+
// reset before exec:
28+
// https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L363-L384
29+
#[cfg(default)]
30+
let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_DFL");
31+
32+
// With #[unix_sigpipe = "sig_dfl"] we get SIG_DFL and the child does too
33+
// without any special code running before exec.
34+
#[cfg(sig_dfl)]
35+
let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL");
36+
37+
// With #[unix_sigpipe = "sig_ign"] we get SIG_IGN and the child does too
38+
// without any special code running before exec.
39+
#[cfg(sig_ign)]
40+
let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_IGN");
41+
42+
// With #[unix_sigpipe = "inherit"] we get SIG_DFL and the child does too
43+
// without any special code running before exec.
44+
#[cfg(inherit)]
45+
let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL");
46+
47+
assert_sigpipe_handler(we_expect);
48+
49+
assert!(
50+
std::process::Command::new("./auxiliary/bin/assert-sigpipe-disposition")
51+
.arg(child_expects)
52+
.status()
53+
.unwrap()
54+
.success()
55+
);
56+
}

tests/ui/compiletest-self-test/test-aux-bin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@ ignore-cross-compile because we run the compiled code
1+
//@ ignore-cross-compile because aux-bin does not yet support it
22
//@ aux-bin: print-it-works.rs
33
//@ run-pass
44

0 commit comments

Comments
 (0)