Skip to content

Commit

Permalink
Prevent Mac cpu_usage() from returning NaN
Browse files Browse the repository at this point in the history
  • Loading branch information
Hoverbear committed Mar 27, 2024
1 parent b7d7f31 commit 829f614
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/unix/apple/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ use libc::{c_char, c_void, host_processor_info, mach_port_t, mach_task_self};
use std::mem;
use std::ops::Deref;
use std::sync::Arc;
use std::time::Instant;

pub(crate) struct CpusWrapper {
pub(crate) global_cpu: Cpu,
pub(crate) cpus: Vec<Cpu>,
pub(crate) got_cpu_frequency: bool,
/// This field is needed to prevent updating when not enough time passed since last update.
last_update: Option<Instant>,
}

impl CpusWrapper {
Expand All @@ -28,13 +31,20 @@ impl CpusWrapper {
},
cpus: Vec::new(),
got_cpu_frequency: false,
last_update: None,
}
}

pub(crate) fn refresh(&mut self, refresh_kind: CpuRefreshKind, port: mach_port_t) {
let need_cpu_usage_update = self
.last_update
.map(|last_update| last_update.elapsed() > crate::MINIMUM_CPU_UPDATE_INTERVAL)
.unwrap_or(true);

let cpus = &mut self.cpus;
if cpus.is_empty() {
init_cpus(port, cpus, &mut self.global_cpu, refresh_kind);
self.last_update = Some(Instant::now());
self.got_cpu_frequency = refresh_kind.frequency();
return;
}
Expand All @@ -45,7 +55,8 @@ impl CpusWrapper {
}
self.got_cpu_frequency = true;
}
if refresh_kind.cpu_usage() {
if refresh_kind.cpu_usage() && need_cpu_usage_update {
self.last_update = Some(Instant::now());
update_cpu_usage(port, &mut self.global_cpu, |proc_data, cpu_info| {
let mut percentage = 0f32;
let mut offset = 0;
Expand Down
15 changes: 15 additions & 0 deletions tests/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,18 @@ fn test_global_cpu_info_not_set() {
assert_eq!(s.global_cpu_info().brand(), "");
assert_eq!(s.global_cpu_info().frequency(), 0);
}

#[test]
fn test_too_rapid_cpu_refresh() {
let mut s = sysinfo::System::new();
assert!(s.cpus().is_empty());

if !sysinfo::IS_SUPPORTED_SYSTEM {
return;
}

s.refresh_cpu();
s.refresh_cpu();

assert!(s.cpus().iter().any(|c| !c.cpu_usage().is_nan()));
}

0 comments on commit 829f614

Please sign in to comment.