Change process spawning to inherit the parent's signal mask by default

Previously, the signal mask is always reset when a child process is
started. This breaks tools like `nohup` which expect `SIGHUP` to be
blocked.

With this change, the default behavior changes to inherit the signal mask.

This also changes the signal disposition for `SIGPIPE` to only be
changed if the `#[unix_sigpipe]` attribute isn't set.
This commit is contained in:
Rain 2022-09-22 22:48:14 -07:00
parent 542febd2d3
commit a52c79e859
8 changed files with 136 additions and 72 deletions

View file

@ -163,17 +163,27 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// See the other file for docs. NOTE: Make sure to keep them in
// sync!
mod sigpipe {
pub const DEFAULT: u8 = 0;
pub const INHERIT: u8 = 1;
pub const SIG_IGN: u8 = 2;
pub const SIG_DFL: u8 = 3;
}
let handler = match sigpipe {
sigpipe::INHERIT => None,
sigpipe::SIG_IGN => Some(libc::SIG_IGN),
sigpipe::SIG_DFL => Some(libc::SIG_DFL),
let (sigpipe_attr_specified, handler) = match sigpipe {
sigpipe::DEFAULT => (false, Some(libc::SIG_IGN)),
sigpipe::INHERIT => (true, None),
sigpipe::SIG_IGN => (true, Some(libc::SIG_IGN)),
sigpipe::SIG_DFL => (true, Some(libc::SIG_DFL)),
_ => unreachable!(),
};
// The bootstrap compiler doesn't know about sigpipe::DEFAULT, and always passes in
// SIG_IGN. This causes some tests to fail because they expect SIGPIPE to be reset to
// default on process spawning (which doesn't happen if #[unix_sigpipe] is specified).
// Since we can't differentiate between the cases here, treat SIG_IGN as DEFAULT
// unconditionally.
if sigpipe_attr_specified && !(cfg!(bootstrap) && sigpipe == sigpipe::SIG_IGN) {
UNIX_SIGPIPE_ATTR_SPECIFIED.store(true, crate::sync::atomic::Ordering::Relaxed);
}
if let Some(handler) = handler {
rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR);
}
@ -181,6 +191,26 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
}
}
// This is set (up to once) in reset_sigpipe.
#[cfg(not(any(
target_os = "espidf",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon"
)))]
static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
crate::sync::atomic::AtomicBool::new(false);
#[cfg(not(any(
target_os = "espidf",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon"
)))]
pub(crate) fn unix_sigpipe_attr_specified() -> bool {
UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed)
}
// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
pub unsafe fn cleanup() {