Skip to content

Commit

Permalink
Protect against NaN and infinities better and in more places
Browse files Browse the repository at this point in the history
  • Loading branch information
nokyan committed Jul 30, 2024
1 parent 34bebef commit 9ad8b7e
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 27 deletions.
7 changes: 4 additions & 3 deletions src/ui/pages/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::ui::widgets::graph_box::ResGraphBox;
use crate::utils::cpu::{CpuData, CpuInfo};
use crate::utils::settings::SETTINGS;
use crate::utils::units::{convert_frequency, convert_temperature};
use crate::utils::{cpu, NaNDefault, NUM_CPUS};
use crate::utils::{cpu, FiniteOr, NUM_CPUS};

mod imp {
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -347,7 +347,8 @@ impl ResCPU {
.saturating_sub(imp.old_total_usage.get().1);
let work_total_time = sum_total_delta.saturating_sub(idle_total_delta);

let total_fraction = ((work_total_time as f64) / (sum_total_delta as f64)).nan_default(0.0);
let total_fraction =
((work_total_time as f64) / (sum_total_delta as f64)).finite_or_default();

imp.total_cpu.graph().push_data_point(total_fraction);

Expand Down Expand Up @@ -375,7 +376,7 @@ impl ResCPU {
let work_thread_time = sum_thread_delta.saturating_sub(idle_thread_delta);
let curr_threadbox = &imp.thread_graphs.borrow()[i];
let thread_fraction =
((work_thread_time as f64) / (sum_thread_delta as f64)).nan_default(0.0);
((work_thread_time as f64) / (sum_thread_delta as f64)).finite_or_default();

curr_threadbox.graph().push_data_point(thread_fraction);
curr_threadbox.set_subtitle(&format!("{} %", (thread_fraction * 100.0).round()));
Expand Down
4 changes: 2 additions & 2 deletions src/ui/pages/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::config::PROFILE;
use crate::i18n::{i18n, i18n_f};
use crate::utils::gpu::{Gpu, GpuData};
use crate::utils::units::{convert_frequency, convert_power, convert_storage, convert_temperature};
use crate::utils::{pci, NaNDefault};
use crate::utils::{pci, FiniteOr};

mod imp {
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -361,7 +361,7 @@ impl ResGPU {

let used_vram_fraction =
if let (Some(total_vram), Some(used_vram)) = (total_vram, used_vram) {
Some((*used_vram as f64 / *total_vram as f64).nan_default(0.0))
Some((*used_vram as f64 / *total_vram as f64).finite_or_default())
} else {
None
};
Expand Down
4 changes: 2 additions & 2 deletions src/ui/pages/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::config::PROFILE;
use crate::i18n::{i18n, i18n_f};
use crate::utils::memory::{self, MemoryData, MemoryDevice};
use crate::utils::units::convert_storage;
use crate::utils::NaNDefault;
use crate::utils::FiniteOr;

mod imp {
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -331,7 +331,7 @@ impl ResMemory {
let used_swap = total_swap.saturating_sub(free_swap);

let memory_fraction = used_mem as f64 / total_mem as f64;
let swap_fraction = (used_swap as f64 / total_swap as f64).nan_default(0.0);
let swap_fraction = (used_swap as f64 / total_swap as f64).finite_or_default();

let formatted_used_mem = convert_storage(used_mem as f64, false);
let formatted_total_mem = convert_storage(total_mem as f64, false);
Expand Down
8 changes: 4 additions & 4 deletions src/utils/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::i18n::i18n;
use super::{
boot_time,
process::{Process, ProcessAction, ProcessItem},
NaNDefault, TICK_RATE,
FiniteOr, TICK_RATE,
};

// This contains executable names that are blacklisted from being recognized as applications
Expand Down Expand Up @@ -479,7 +479,7 @@ impl AppsContext {
} else {
((new.gfx.saturating_sub(old.gfx) as f32)
/ (timestamp.saturating_sub(timestamp_last) as f32))
.nan_default(0.0)
.finite_or_default()
/ 1_000_000.0
}
})
Expand Down Expand Up @@ -517,7 +517,7 @@ impl AppsContext {
} else {
((new.enc.saturating_sub(old.enc) as f32)
/ (timestamp.saturating_sub(timestamp_last) as f32))
.nan_default(0.0)
.finite_or_default()
/ 1_000_000.0
}
})
Expand Down Expand Up @@ -555,7 +555,7 @@ impl AppsContext {
} else {
((new.dec.saturating_sub(old.dec) as f32)
/ (timestamp.saturating_sub(timestamp_last) as f32))
.nan_default(0.0)
.finite_or_default()
/ 1_000_000.0
}
})
Expand Down
68 changes: 57 additions & 11 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,73 @@ pub fn boot_time() -> Result<DateTime> {
})
}

pub trait NaNDefault {
/// Returns the given `default` value if the variable is NaN,
pub trait FiniteOr {
/// Returns the given `x` value if the variable is NaN or infinite,
/// and returns itself otherwise.
#[must_use]
fn nan_default(&self, default: Self) -> Self;
fn finite_or(&self, x: Self) -> Self;

/// Returns itself is the variable is finite (i.e. neither NaN nor infinite), otherwise returns its default
fn finite_or_default(&self) -> Self;

/// Returns itself is the variable is finite (i.e. neither NaN nor infinite), otherwise runs `f`
fn finite_or_else<F: FnOnce(Self) -> Self>(&self, f: F) -> Self
where
Self: Sized;
}

impl NaNDefault for f64 {
fn nan_default(&self, default: Self) -> Self {
if self.is_nan() {
default
impl FiniteOr for f64 {
fn finite_or(&self, x: Self) -> Self {
if !self.is_finite() {
x
} else {
*self
}
}

fn finite_or_default(&self) -> Self {
if !self.is_finite() {
Self::default()
} else {
*self
}
}

fn finite_or_else<F: FnOnce(Self) -> Self>(&self, f: F) -> Self
where
Self: Sized,
{
if !self.is_finite() {
f(*self)
} else {
*self
}
}
}

impl NaNDefault for f32 {
fn nan_default(&self, default: Self) -> Self {
if self.is_nan() {
default
impl FiniteOr for f32 {
fn finite_or(&self, x: Self) -> Self {
if !self.is_finite() {
x
} else {
*self
}
}

fn finite_or_default(&self) -> Self {
if !self.is_finite() {
Self::default()
} else {
*self
}
}

fn finite_or_else<F: FnOnce(Self) -> Self>(&self, f: F) -> Self
where
Self: Sized,
{
if !self.is_finite() {
f(*self)
} else {
*self
}
Expand Down
11 changes: 6 additions & 5 deletions src/utils/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use gtk::gio::{Icon, ThemedIcon};

use crate::config;

use super::{NaNDefault, FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK, NUM_CPUS, TICK_RATE};
use super::{FiniteOr, FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK, NUM_CPUS, TICK_RATE};

static OTHER_PROCESS: LazyLock<Mutex<(ChildStdin, ChildStdout)>> = LazyLock::new(|| {
let proxy_path = if *IS_FLATPAK {
Expand Down Expand Up @@ -289,7 +289,8 @@ impl Process {
* 1000.0;
let delta_time = self.data.timestamp.saturating_sub(self.timestamp_last);

delta_cpu_time / (delta_time * *TICK_RATE as u64 * *NUM_CPUS as u64) as f32
(delta_cpu_time / (delta_time * *TICK_RATE as u64 * *NUM_CPUS as u64) as f32)
.finite_or_default()
}
}

Expand Down Expand Up @@ -339,7 +340,7 @@ impl Process {
} else {
((usage.gfx.saturating_sub(old_usage.gfx) as f32)
/ (self.data.timestamp.saturating_sub(self.timestamp_last) as f32)
.nan_default(0.0))
.finite_or_default())
/ 1_000_000.0
};

Expand All @@ -364,7 +365,7 @@ impl Process {
} else {
((usage.enc.saturating_sub(old_usage.enc) as f32)
/ (self.data.timestamp.saturating_sub(self.timestamp_last) as f32)
.nan_default(0.0))
.finite_or_default())
/ 1_000_000.0
};

Expand All @@ -389,7 +390,7 @@ impl Process {
} else {
((usage.dec.saturating_sub(old_usage.dec) as f32)
/ (self.data.timestamp.saturating_sub(self.timestamp_last) as f32)
.nan_default(0.0))
.finite_or_default())
/ 1_000_000.0
};

Expand Down

0 comments on commit 9ad8b7e

Please sign in to comment.