Consolidate sigemptyset workarounds

In sys/unix/process, we work around the sigemptyset linking issues
on android in two different ways. This change consolidates these
workarounds, and avoids duplicating bindings from `libc`.
This commit is contained in:
Joe Richey 2019-08-19 16:14:07 -07:00
parent 29a54035c7
commit 8e91dca596
2 changed files with 27 additions and 40 deletions

View File

@ -20,6 +20,30 @@ cfg_if::cfg_if! {
}
}
// Android with api less than 21 define sig* functions inline, so it is not
// available for dynamic link. Implementing sigemptyset and sigaddset allow us
// to support older Android version (independent of libc version).
// The following implementations are based on https://git.io/vSkNf
cfg_if::cfg_if! {
if #[cfg(target_os = "android")] {
pub unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
set.write_bytes(0u8, 1);
return 0;
}
#[allow(dead_code)]
pub unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
use crate::{slice, mem};
let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>());
let bit = (signum - 1) as usize;
raw[bit / 8] |= 1 << (bit % 8);
return 0;
}
} else {
pub use libc::{sigemptyset, sigaddset};
}
}
////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////
@ -429,36 +453,6 @@ mod tests {
}
}
// Android with api less than 21 define sig* functions inline, so it is not
// available for dynamic link. Implementing sigemptyset and sigaddset allow us
// to support older Android version (independent of libc version).
// The following implementations are based on https://git.io/vSkNf
#[cfg(not(target_os = "android"))]
extern {
#[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int;
#[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int;
}
#[cfg(target_os = "android")]
unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
set.write_bytes(0u8, 1);
return 0;
}
#[cfg(target_os = "android")]
unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
use crate::slice;
let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>());
let bit = (signum - 1) as usize;
raw[bit / 8] |= 1 << (bit % 8);
return 0;
}
// See #14232 for more information, but it appears that signal delivery to a
// newly spawned process may just be raced in the macOS, so to prevent this
// test from being flaky we ignore it on macOS.

View File

@ -214,14 +214,7 @@ impl Command {
// need to clean things up now to avoid confusing the program
// we're about to run.
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
if cfg!(target_os = "android") {
// Implementing sigemptyset allow us to support older Android
// versions. See the comment about Android and sig* functions in
// process_common.rs
set.as_mut_ptr().write_bytes(0u8, 1);
} else {
cvt(libc::sigemptyset(set.as_mut_ptr()))?;
}
cvt(sigemptyset(set.as_mut_ptr()))?;
cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(),
ptr::null_mut()))?;
let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
@ -363,10 +356,10 @@ impl Command {
}
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
cvt(libc::sigemptyset(set.as_mut_ptr()))?;
cvt(sigemptyset(set.as_mut_ptr()))?;
cvt(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(),
set.as_ptr()))?;
cvt(libc::sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
cvt(sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
cvt(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(),
set.as_ptr()))?;