Skip to content

Commit

Permalink
Merge pull request #974 from GuillaumeGomez/eintr
Browse files Browse the repository at this point in the history
Correctly handle EINTR
  • Loading branch information
GuillaumeGomez committed Apr 30, 2023
2 parents a21fd2a + ce52a42 commit 02af6ab
Show file tree
Hide file tree
Showing 13 changed files with 48 additions and 18 deletions.
3 changes: 1 addition & 2 deletions .cirrus.yml
Expand Up @@ -3,7 +3,6 @@ task:
freebsd_instance:
image: freebsd-13-1-release-amd64
setup_script:
- pkg install -y curl
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh -y --profile=minimal --default-toolchain=1.59
- . $HOME/.cargo/env
Expand All @@ -23,7 +22,6 @@ task:
freebsd_instance:
image: freebsd-13-1-release-amd64
setup_script:
- pkg install -y curl
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh -y --profile=minimal --default-toolchain=nightly
- . $HOME/.cargo/env
Expand All @@ -43,6 +41,7 @@ task:
macos_instance:
image: ghcr.io/cirruslabs/macos-monterey-base:latest
setup_script:
- brew update
- brew install curl
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh -y --profile=minimal --default-toolchain=1.59
Expand Down
2 changes: 1 addition & 1 deletion src/apple/macos/process.rs
Expand Up @@ -189,7 +189,7 @@ impl ProcessExt for Process {
let mut status = 0;
// attempt waiting
unsafe {
if libc::waitpid(self.pid.0, &mut status, 0) < 0 {
if retry_eintr!(libc::waitpid(self.pid.0, &mut status, 0)) < 0 {
// attempt failed (non-child process) so loop until process ends
let duration = std::time::Duration::from_millis(10);
while kill(self.pid.0, 0) == 0 {
Expand Down
2 changes: 1 addition & 1 deletion src/apple/network.rs
Expand Up @@ -84,7 +84,7 @@ impl Networks {
let name = String::from_utf8_unchecked(name);
match self.interfaces.entry(name) {
hash_map::Entry::Occupied(mut e) => {
let mut interface = e.get_mut();
let interface = e.get_mut();
old_and_new!(
interface,
current_out,
Expand Down
26 changes: 22 additions & 4 deletions src/apple/users.rs
Expand Up @@ -23,11 +23,25 @@ fn get_user_groups(name: *const c_char, group_id: gid_t) -> Vec<String> {
return groups
.into_iter()
.filter_map(|g| {
let group = getgrgid(g as _);
if group.is_null() {
return None;
let errno = libc::__error();

loop {
// As mentioned in the man, we set `errno` to 0 to ensure that if a problem
// occurs and errno is 0, then it means this group doesn't exist.
if !errno.is_null() {
*errno = 0;
}

let group = getgrgid(g as _);
if group.is_null() {
// The call was interrupted by a signal, retrying.
if !errno.is_null() && *errno == libc::EINTR {
continue;
}
return None;
}
return utils::cstr_to_rust((*group).gr_name);
}
utils::cstr_to_rust((*group).gr_name)
})
.collect();
}
Expand Down Expand Up @@ -60,6 +74,10 @@ where
loop {
let pw = getpwent();
if pw.is_null() {
// The call was interrupted by a signal, retrying.
if std::io::Error::last_os_error().kind() == std::io::ErrorKind::Interrupted {
continue;
}
break;
}

Expand Down
2 changes: 1 addition & 1 deletion src/freebsd/network.rs
Expand Up @@ -88,7 +88,7 @@ impl Networks {
let data = &data.ifmd_data;
match self.interfaces.entry(name) {
hash_map::Entry::Occupied(mut e) => {
let mut interface = e.get_mut();
let interface = e.get_mut();

old_and_new!(interface, ifi_ibytes, old_ifi_ibytes, data);
old_and_new!(interface, ifi_obytes, old_ifi_obytes, data);
Expand Down
2 changes: 1 addition & 1 deletion src/freebsd/process.rs
Expand Up @@ -148,7 +148,7 @@ impl ProcessExt for Process {
let mut status = 0;
// attempt waiting
unsafe {
if libc::waitpid(self.pid.0, &mut status, 0) < 0 {
if retry_eintr!(libc::waitpid(self.pid.0, &mut status, 0)) < 0 {
// attempt failed (non-child process) so loop until process ends
let duration = std::time::Duration::from_millis(10);
while kill(self.pid.0, 0) == 0 {
Expand Down
4 changes: 2 additions & 2 deletions src/freebsd/utils.rs
Expand Up @@ -98,7 +98,7 @@ pub(crate) unsafe fn get_sys_value<T: Sized>(mib: &[c_int], value: &mut T) -> bo
}

pub(crate) unsafe fn get_sys_value_array<T: Sized>(mib: &[c_int], value: &mut [T]) -> bool {
let mut len = (mem::size_of::<T>() * value.len()) as libc::size_t;
let mut len = mem::size_of_val(value) as libc::size_t;
libc::sysctl(
mib.as_ptr(),
mib.len() as _,
Expand Down Expand Up @@ -126,7 +126,7 @@ pub(crate) fn c_buf_to_string(buf: &[libc::c_char]) -> Option<String> {
}

pub(crate) unsafe fn get_sys_value_str(mib: &[c_int], buf: &mut [libc::c_char]) -> Option<String> {
let mut len = (mem::size_of::<libc::c_char>() * buf.len()) as libc::size_t;
let mut len = mem::size_of_val(buf) as libc::size_t;
if libc::sysctl(
mib.as_ptr(),
mib.len() as _,
Expand Down
4 changes: 2 additions & 2 deletions src/linux/disk.rs
Expand Up @@ -61,7 +61,7 @@ impl DiskExt for Disk {
unsafe {
let mut stat: statvfs = mem::zeroed();
let mount_point_cpath = to_cpath(&self.mount_point);
if statvfs(mount_point_cpath.as_ptr() as *const _, &mut stat) == 0 {
if retry_eintr!(statvfs(mount_point_cpath.as_ptr() as *const _, &mut stat)) == 0 {
let tmp = cast!(stat.f_bsize).saturating_mul(cast!(stat.f_bavail));
self.available_space = cast!(tmp);
true
Expand All @@ -84,7 +84,7 @@ fn new_disk(
let mut available = 0;
unsafe {
let mut stat: statvfs = mem::zeroed();
if statvfs(mount_point_cpath.as_ptr() as *const _, &mut stat) == 0 {
if retry_eintr!(statvfs(mount_point_cpath.as_ptr() as *const _, &mut stat)) == 0 {
let bsize = cast!(stat.f_bsize);
let blocks = cast!(stat.f_blocks);
let bavail = cast!(stat.f_bavail);
Expand Down
2 changes: 1 addition & 1 deletion src/linux/network.rs
Expand Up @@ -79,7 +79,7 @@ fn refresh_networks_list_from_sysfs(
// let tx_compressed = read(parent, "tx_compressed", &mut data);
match interfaces.entry(entry) {
hash_map::Entry::Occupied(mut e) => {
let mut interface = e.get_mut();
let interface = e.get_mut();
old_and_new!(interface, rx_bytes, old_rx_bytes);
old_and_new!(interface, tx_bytes, old_tx_bytes);
old_and_new!(interface, rx_packets, old_rx_packets);
Expand Down
2 changes: 1 addition & 1 deletion src/linux/process.rs
Expand Up @@ -212,7 +212,7 @@ impl ProcessExt for Process {
let mut status = 0;
// attempt waiting
unsafe {
if libc::waitpid(self.pid.0, &mut status, 0) < 0 {
if retry_eintr!(libc::waitpid(self.pid.0, &mut status, 0)) < 0 {
// attempt failed (non-child process) so loop until process ends
let duration = std::time::Duration::from_millis(10);
while kill(self.pid.0, 0) == 0 {
Expand Down
13 changes: 13 additions & 0 deletions src/macros.rs
Expand Up @@ -56,3 +56,16 @@ macro_rules! declare_signals {
}
)
}

#[cfg(all(unix, not(feature = "unknown-ci")))]
macro_rules! retry_eintr {
($($t:tt)+) => {
loop {
let ret = $($t)+;
if ret < 0 && std::io::Error::last_os_error().kind() == std::io::ErrorKind::Interrupted {
continue;
}
break ret;
}
}
}
2 changes: 1 addition & 1 deletion src/network_helper_nix.rs
Expand Up @@ -105,7 +105,7 @@ unsafe fn parse_interface_address(ifap: *const libc::ifaddrs) -> Option<MacAddr>
pub(crate) fn get_interface_address() -> Result<InterfaceAddressIterator, String> {
let mut ifap = null_mut();
unsafe {
if libc::getifaddrs(&mut ifap) == 0 && !ifap.is_null() {
if retry_eintr!(libc::getifaddrs(&mut ifap)) == 0 && !ifap.is_null() {
Ok(InterfaceAddressIterator { ifap, buf: ifap })
} else {
Err("failed to call getifaddrs()".to_string())
Expand Down
2 changes: 1 addition & 1 deletion src/windows/network.rs
Expand Up @@ -102,7 +102,7 @@ impl NetworksExt for Networks {
};
match self.interfaces.entry(interface_name) {
hash_map::Entry::Occupied(mut e) => {
let mut interface = e.get_mut();
let interface = e.get_mut();
old_and_new!(interface, current_out, old_out, ptr.OutOctets);
old_and_new!(interface, current_in, old_in, ptr.InOctets);
old_and_new!(
Expand Down

0 comments on commit 02af6ab

Please sign in to comment.