mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-21 19:53:05 +00:00
bug: add bindings to grab ppid in some cases on macos (#825)
This commit is contained in:
parent
e7b31dfb96
commit
1e5f0ea2d9
6 changed files with 393 additions and 26 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -227,6 +227,7 @@ dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
"mach2",
|
||||||
"nvml-wrapper",
|
"nvml-wrapper",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"predicates",
|
"predicates",
|
||||||
|
@ -967,6 +968,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mach2"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.4.1"
|
version = "2.4.1"
|
||||||
|
|
26
Cargo.toml
26
Cargo.toml
|
@ -61,7 +61,6 @@ concat-string = "1.0.1"
|
||||||
crossterm = "0.18.2"
|
crossterm = "0.18.2"
|
||||||
ctrlc = { version = "3.1.9", features = ["termination"] }
|
ctrlc = { version = "3.1.9", features = ["termination"] }
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
|
|
||||||
fern = { version = "0.6.1", optional = true }
|
fern = { version = "0.6.1", optional = true }
|
||||||
futures = "0.3.21"
|
futures = "0.3.21"
|
||||||
futures-timer = "3.0.2"
|
futures-timer = "3.0.2"
|
||||||
|
@ -93,6 +92,7 @@ smol = "1.2.5"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory", "net"] }
|
heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory", "net"] }
|
||||||
|
mach2 = "0.4.1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory"] }
|
heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory"] }
|
||||||
|
@ -114,9 +114,21 @@ clap_mangen = "0.1.6"
|
||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
section = "utility"
|
section = "utility"
|
||||||
assets = [
|
assets = [
|
||||||
["target/release/btm", "usr/bin/", "755"],
|
[
|
||||||
["LICENSE", "usr/share/doc/btm/", "644"],
|
"target/release/btm",
|
||||||
["manpage/btm.1.gz", "usr/share/man/man1/btm.1.gz", "644"],
|
"usr/bin/",
|
||||||
|
"755",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"LICENSE",
|
||||||
|
"usr/share/doc/btm/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"manpage/btm.1.gz",
|
||||||
|
"usr/share/man/man1/btm.1.gz",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"completion/btm.bash",
|
"completion/btm.bash",
|
||||||
"usr/share/bash-completion/completions/btm",
|
"usr/share/bash-completion/completions/btm",
|
||||||
|
@ -127,7 +139,11 @@ assets = [
|
||||||
"usr/share/fish/vendor_completions.d/btm.fish",
|
"usr/share/fish/vendor_completions.d/btm.fish",
|
||||||
"644",
|
"644",
|
||||||
],
|
],
|
||||||
["completion/_btm", "usr/share/zsh/vendor-completions/", "644"],
|
[
|
||||||
|
"completion/_btm",
|
||||||
|
"usr/share/zsh/vendor-completions/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
]
|
]
|
||||||
extended-description = """\
|
extended-description = """\
|
||||||
A customizable cross-platform graphical process/system monitor for the terminal. Supports Linux, macOS, and Windows.
|
A customizable cross-platform graphical process/system monitor for the terminal. Supports Linux, macOS, and Windows.
|
||||||
|
|
|
@ -110,21 +110,17 @@ impl ProcessData {
|
||||||
.collect();
|
.collect();
|
||||||
self.process_harvest = process_pid_map;
|
self.process_harvest = process_pid_map;
|
||||||
|
|
||||||
// This also needs a quick sort + reverse to be in the correct order.
|
// We collect all processes that either:
|
||||||
|
// - Do not have a parent PID (that is, they are orphan processes)
|
||||||
|
// - Have a parent PID but we don't have the parent (we promote them as orphans)
|
||||||
|
// Note this also needs a quick sort + reverse to be in the correct order.
|
||||||
self.orphan_pids = {
|
self.orphan_pids = {
|
||||||
let mut res: Vec<Pid> = self
|
let mut res: Vec<Pid> = self
|
||||||
.process_harvest
|
.process_harvest
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(pid, process_harvest)| {
|
.filter_map(|(pid, process_harvest)| match process_harvest.parent_pid {
|
||||||
if let Some(parent_pid) = process_harvest.parent_pid {
|
Some(parent_pid) if self.process_harvest.contains_key(&parent_pid) => None,
|
||||||
if self.process_harvest.contains_key(&parent_pid) {
|
_ => Some(*pid),
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(*pid)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Some(*pid)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.sorted()
|
.sorted()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
//! Process data collection for macOS. Uses sysinfo.
|
//! Process data collection for macOS. Uses sysinfo and custom bindings.
|
||||||
|
|
||||||
use super::ProcessHarvest;
|
use super::ProcessHarvest;
|
||||||
use sysinfo::System;
|
use sysinfo::System;
|
||||||
|
|
||||||
use crate::data_harvester::processes::UserTable;
|
use crate::{data_harvester::processes::UserTable, Pid};
|
||||||
|
mod sysctl_bindings;
|
||||||
|
|
||||||
pub fn get_process_data(
|
pub fn get_process_data(
|
||||||
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, user_table: &mut UserTable,
|
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, user_table: &mut UserTable,
|
||||||
|
@ -17,8 +18,14 @@ pub fn get_process_data(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn fallback_macos_ppid(pid: Pid) -> Option<Pid> {
|
||||||
|
sysctl_bindings::kinfo_process(pid)
|
||||||
|
.map(|kinfo| kinfo.kp_eproc.e_ppid)
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_macos_process_cpu_usage(
|
fn get_macos_process_cpu_usage(
|
||||||
pids: &[i32],
|
pids: &[Pid],
|
||||||
) -> std::io::Result<std::collections::HashMap<i32, f64>> {
|
) -> std::io::Result<std::collections::HashMap<i32, f64>> {
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
let output = std::process::Command::new("ps")
|
let output = std::process::Command::new("ps")
|
||||||
|
|
322
src/app/data_harvester/processes/macos/sysctl_bindings.rs
Normal file
322
src/app/data_harvester/processes/macos/sysctl_bindings.rs
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
//! Partial bindings from Apple's open source code for getting process information.
|
||||||
|
//! Some of this is based on [heim's binding implementation](https://github.com/heim-rs/heim/blob/master/heim-process/src/sys/macos/bindings/process.rs).
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use libc::{
|
||||||
|
boolean_t, c_char, c_long, c_short, c_uchar, c_ushort, c_void, dev_t, gid_t, itimerval, pid_t,
|
||||||
|
rusage, sigset_t, timeval, uid_t, xucred, CTL_KERN, KERN_PROC, KERN_PROC_PID, MAXCOMLEN,
|
||||||
|
};
|
||||||
|
use mach2::vm_types::user_addr_t;
|
||||||
|
|
||||||
|
use crate::Pid;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub(crate) struct kinfo_proc {
|
||||||
|
pub kp_proc: extern_proc,
|
||||||
|
pub kp_eproc: eproc,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct p_st1 {
|
||||||
|
/// Doubly-linked run/sleep queue.
|
||||||
|
p_forw: user_addr_t,
|
||||||
|
p_back: user_addr_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub union p_un {
|
||||||
|
pub p_st1: p_st1,
|
||||||
|
|
||||||
|
/// process start time
|
||||||
|
pub p_starttime: timeval,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Exported fields for kern sysctl. See
|
||||||
|
/// [`proc.h`](https://opensource.apple.com/source/xnu/xnu-201/bsd/sys/proc.h)
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub(crate) struct extern_proc {
|
||||||
|
pub p_un: p_un,
|
||||||
|
|
||||||
|
/// Address space.
|
||||||
|
pub p_vmspace: *mut vmspace,
|
||||||
|
|
||||||
|
/// Signal actions, state (PROC ONLY). Should point to
|
||||||
|
/// a `sigacts` but we don't really seem to need this.
|
||||||
|
pub p_sigacts: user_addr_t,
|
||||||
|
|
||||||
|
/// P_* flags.
|
||||||
|
pub p_flag: i32,
|
||||||
|
|
||||||
|
/// S* process status.
|
||||||
|
pub p_stat: c_char,
|
||||||
|
|
||||||
|
/// Process identifier.
|
||||||
|
pub p_pid: pid_t,
|
||||||
|
|
||||||
|
/// Save parent pid during ptrace. XXX
|
||||||
|
pub p_oppid: pid_t,
|
||||||
|
|
||||||
|
/// Sideways return value from fdopen. XXX
|
||||||
|
pub p_dupfd: i32,
|
||||||
|
|
||||||
|
/// where user stack was allocated
|
||||||
|
pub user_stack: caddr_t,
|
||||||
|
|
||||||
|
/// XXX Which thread is exiting?
|
||||||
|
pub exit_thread: *mut c_void,
|
||||||
|
|
||||||
|
/// allow to debug
|
||||||
|
pub p_debugger: i32,
|
||||||
|
|
||||||
|
/// indication to suspend
|
||||||
|
pub sigwait: boolean_t,
|
||||||
|
|
||||||
|
/// Time averaged value of p_cpticks.
|
||||||
|
pub p_estcpu: u32,
|
||||||
|
|
||||||
|
/// Ticks of cpu time.
|
||||||
|
pub p_cpticks: i32,
|
||||||
|
|
||||||
|
/// %cpu for this process during p_swtime
|
||||||
|
pub p_pctcpu: fixpt_t,
|
||||||
|
|
||||||
|
/// Sleep address.
|
||||||
|
pub p_wchan: *mut c_void,
|
||||||
|
|
||||||
|
/// Reason for sleep.
|
||||||
|
pub p_wmesg: *mut c_char,
|
||||||
|
|
||||||
|
/// Time swapped in or out.
|
||||||
|
pub p_swtime: u32,
|
||||||
|
|
||||||
|
/// Time since last blocked.
|
||||||
|
pub p_slptime: u32,
|
||||||
|
|
||||||
|
/// Alarm timer.
|
||||||
|
pub p_realtimer: itimerval,
|
||||||
|
|
||||||
|
/// Real time.
|
||||||
|
pub p_rtime: timeval,
|
||||||
|
|
||||||
|
/// Statclock hit in user mode.
|
||||||
|
pub p_uticks: u64,
|
||||||
|
|
||||||
|
/// Statclock hits in system mode.
|
||||||
|
pub p_sticks: u64,
|
||||||
|
|
||||||
|
/// Statclock hits processing intr.
|
||||||
|
pub p_iticks: u64,
|
||||||
|
|
||||||
|
/// Kernel trace points.
|
||||||
|
pub p_traceflag: i32,
|
||||||
|
|
||||||
|
/// Trace to vnode. Originally a pointer to a struct of vnode.
|
||||||
|
pub p_tracep: *mut c_void,
|
||||||
|
|
||||||
|
/// DEPRECATED.
|
||||||
|
pub p_siglist: i32,
|
||||||
|
|
||||||
|
/// Vnode of executable. Originally a pointer to a struct of vnode.
|
||||||
|
pub p_textvp: *mut c_void,
|
||||||
|
|
||||||
|
/// If non-zero, don't swap.
|
||||||
|
pub p_holdcnt: i32,
|
||||||
|
|
||||||
|
/// DEPRECATED.
|
||||||
|
pub p_sigmask: sigset_t,
|
||||||
|
|
||||||
|
/// Signals being ignored.
|
||||||
|
pub p_sigignore: sigset_t,
|
||||||
|
|
||||||
|
/// Signals being caught by user.
|
||||||
|
pub p_sigcatch: sigset_t,
|
||||||
|
|
||||||
|
/// Process priority.
|
||||||
|
pub p_priority: c_uchar,
|
||||||
|
|
||||||
|
/// User-priority based on p_cpu and p_nice.
|
||||||
|
pub p_usrpri: c_uchar,
|
||||||
|
|
||||||
|
/// Process "nice" value.
|
||||||
|
pub p_nice: c_char,
|
||||||
|
|
||||||
|
pub p_comm: [c_char; MAXCOMLEN + 1],
|
||||||
|
|
||||||
|
/// Pointer to process group. Originally a pointer to a `pgrp`.
|
||||||
|
pub p_pgrp: *mut c_void,
|
||||||
|
|
||||||
|
/// Kernel virtual addr of u-area (PROC ONLY). Originally a pointer to a `user`.
|
||||||
|
pub p_addr: *mut c_void,
|
||||||
|
|
||||||
|
/// Exit status for wait; also stop signal.
|
||||||
|
pub p_xstat: c_ushort,
|
||||||
|
|
||||||
|
/// Accounting flags.
|
||||||
|
pub p_acflag: c_ushort,
|
||||||
|
|
||||||
|
/// Exit information. XXX
|
||||||
|
pub p_ru: *mut rusage,
|
||||||
|
}
|
||||||
|
|
||||||
|
const WMESGLEN: usize = 7;
|
||||||
|
const COMAPT_MAXLOGNAME: usize = 12;
|
||||||
|
|
||||||
|
/// See `_caddr_t.h`.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type caddr_t = *const libc::c_char;
|
||||||
|
|
||||||
|
/// See `types.h`.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type segsz_t = i32;
|
||||||
|
|
||||||
|
/// See `types.h`.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type fixpt_t = u32;
|
||||||
|
|
||||||
|
/// See [`proc.h`](https://opensource.apple.com/source/xnu/xnu-201/bsd/sys/proc.h)
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub(crate) struct pcred {
|
||||||
|
pub pc_lock: [c_char; 72],
|
||||||
|
pub pc_ucred: *mut xucred,
|
||||||
|
pub p_ruid: uid_t,
|
||||||
|
pub p_svuid: uid_t,
|
||||||
|
pub p_rgid: gid_t,
|
||||||
|
pub p_svgid: gid_t,
|
||||||
|
pub p_refcnt: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See `vm.h`.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub(crate) struct vmspace {
|
||||||
|
pub dummy: i32,
|
||||||
|
pub dummy2: caddr_t,
|
||||||
|
pub dummy3: [i32; 5],
|
||||||
|
pub dummy4: [caddr_t; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See [`sysctl.h`](https://opensource.apple.com/source/xnu/xnu-344/bsd/sys/sysctl.h).
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub(crate) struct eproc {
|
||||||
|
/// Address of proc. We just cheat and use a c_void pointer since we aren't using this.
|
||||||
|
pub e_paddr: *mut c_void,
|
||||||
|
|
||||||
|
/// Session pointer. We just cheat and use a c_void pointer since we aren't using this.
|
||||||
|
pub e_sess: *mut c_void,
|
||||||
|
|
||||||
|
/// Process credentials
|
||||||
|
pub e_pcred: pcred,
|
||||||
|
|
||||||
|
/// Current credentials
|
||||||
|
pub e_ucred: xucred,
|
||||||
|
|
||||||
|
/// Address space
|
||||||
|
pub e_vm: vmspace,
|
||||||
|
|
||||||
|
/// Parent process ID
|
||||||
|
pub e_ppid: pid_t,
|
||||||
|
|
||||||
|
/// Process group ID
|
||||||
|
pub e_pgid: pid_t,
|
||||||
|
|
||||||
|
/// Job control counter
|
||||||
|
pub e_jobc: c_short,
|
||||||
|
|
||||||
|
/// Controlling tty dev
|
||||||
|
pub e_tdev: dev_t,
|
||||||
|
|
||||||
|
/// tty process group id
|
||||||
|
pub e_tpgid: pid_t,
|
||||||
|
|
||||||
|
/// tty session pointer. We just cheat and use a c_void pointer since we aren't using this.
|
||||||
|
pub e_tsess: *mut c_void,
|
||||||
|
|
||||||
|
/// wchan message
|
||||||
|
pub e_wmesg: [c_char; WMESGLEN + 1],
|
||||||
|
|
||||||
|
/// text size
|
||||||
|
pub e_xsize: segsz_t,
|
||||||
|
|
||||||
|
/// text rss
|
||||||
|
pub e_xrssize: c_short,
|
||||||
|
|
||||||
|
/// text references
|
||||||
|
pub e_xccount: c_short,
|
||||||
|
|
||||||
|
pub e_xswrss: c_short,
|
||||||
|
|
||||||
|
pub e_flag: c_long,
|
||||||
|
|
||||||
|
/// short setlogin() name
|
||||||
|
pub e_login: [c_char; COMAPT_MAXLOGNAME],
|
||||||
|
|
||||||
|
pub e_spare: [c_long; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains the [`kinfo_proc`] given a process PID.
|
||||||
|
///
|
||||||
|
/// From [heim](https://github.com/heim-rs/heim/blob/master/heim-process/src/sys/macos/bindings/process.rs#L235).
|
||||||
|
pub(crate) fn kinfo_process(pid: Pid) -> Result<kinfo_proc> {
|
||||||
|
let mut name: [i32; 4] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, pid];
|
||||||
|
let mut size = mem::size_of::<kinfo_proc>();
|
||||||
|
let mut info = mem::MaybeUninit::<kinfo_proc>::uninit();
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
libc::sysctl(
|
||||||
|
name.as_mut_ptr(),
|
||||||
|
4,
|
||||||
|
info.as_mut_ptr() as *mut libc::c_void,
|
||||||
|
&mut size,
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if result < 0 {
|
||||||
|
bail!("failed to get process for pid {pid}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// sysctl succeeds but size is zero, happens when process has gone away
|
||||||
|
if size == 0 {
|
||||||
|
bail!("failed to get process for pid {pid}");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { Ok(info.assume_init()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
/// A quick test to ensure that things are sized correctly.
|
||||||
|
#[test]
|
||||||
|
fn test_struct_sizes() {
|
||||||
|
assert_eq!(mem::size_of::<p_st1>(), 16);
|
||||||
|
assert_eq!(mem::align_of::<p_st1>(), 8);
|
||||||
|
|
||||||
|
assert_eq!(mem::size_of::<pcred>(), 104);
|
||||||
|
assert_eq!(mem::align_of::<pcred>(), 8);
|
||||||
|
|
||||||
|
assert_eq!(mem::size_of::<vmspace>(), 64);
|
||||||
|
assert_eq!(mem::align_of::<vmspace>(), 8);
|
||||||
|
|
||||||
|
assert_eq!(mem::size_of::<extern_proc>(), 296);
|
||||||
|
assert_eq!(mem::align_of::<extern_proc>(), 8);
|
||||||
|
|
||||||
|
assert_eq!(mem::size_of::<eproc>(), 376);
|
||||||
|
assert_eq!(mem::align_of::<eproc>(), 8);
|
||||||
|
|
||||||
|
assert_eq!(mem::size_of::<kinfo_proc>(), 672);
|
||||||
|
assert_eq!(mem::align_of::<kinfo_proc>(), 8);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,12 +6,15 @@ use std::io;
|
||||||
use super::ProcessHarvest;
|
use super::ProcessHarvest;
|
||||||
use sysinfo::{CpuExt, PidExt, ProcessExt, ProcessStatus, System, SystemExt};
|
use sysinfo::{CpuExt, PidExt, ProcessExt, ProcessStatus, System, SystemExt};
|
||||||
|
|
||||||
use crate::data_harvester::processes::UserTable;
|
use crate::{data_harvester::processes::UserTable, utils::error::Result, Pid};
|
||||||
|
|
||||||
pub fn get_process_data(
|
pub fn get_process_data<F>(
|
||||||
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, user_table: &mut UserTable,
|
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, user_table: &mut UserTable,
|
||||||
get_process_cpu_usage: impl Fn(&[i32]) -> io::Result<HashMap<i32, f64>>,
|
get_process_cpu_usage: F,
|
||||||
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
|
) -> Result<Vec<ProcessHarvest>>
|
||||||
|
where
|
||||||
|
F: Fn(&[Pid]) -> io::Result<HashMap<Pid, f64>>,
|
||||||
|
{
|
||||||
let mut process_vector: Vec<ProcessHarvest> = Vec::new();
|
let mut process_vector: Vec<ProcessHarvest> = Vec::new();
|
||||||
let process_hashmap = sys.processes();
|
let process_hashmap = sys.processes();
|
||||||
let cpu_usage = sys.global_cpu_info().cpu_usage() as f64 / 100.0;
|
let cpu_usage = sys.global_cpu_info().cpu_usage() as f64 / 100.0;
|
||||||
|
@ -66,9 +69,22 @@ pub fn get_process_data(
|
||||||
(ps.to_string(), convert_process_status_to_char(ps))
|
(ps.to_string(), convert_process_status_to_char(ps))
|
||||||
};
|
};
|
||||||
let uid = process_val.user_id().map(|u| **u);
|
let uid = process_val.user_id().map(|u| **u);
|
||||||
|
let pid = process_val.pid().as_u32() as Pid;
|
||||||
process_vector.push(ProcessHarvest {
|
process_vector.push(ProcessHarvest {
|
||||||
pid: process_val.pid().as_u32() as _,
|
pid,
|
||||||
parent_pid: process_val.parent().map(|p| p.as_u32() as _),
|
parent_pid: {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
process_val
|
||||||
|
.parent()
|
||||||
|
.map(|p| p.as_u32() as _)
|
||||||
|
.or_else(|| super::fallback_macos_ppid(pid))
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
{
|
||||||
|
process_val.parent().map(|p| p.as_u32() as _)
|
||||||
|
}
|
||||||
|
},
|
||||||
name,
|
name,
|
||||||
command,
|
command,
|
||||||
mem_usage_percent: if mem_total_kb > 0 {
|
mem_usage_percent: if mem_total_kb > 0 {
|
||||||
|
@ -96,7 +112,7 @@ pub fn get_process_data(
|
||||||
}
|
}
|
||||||
|
|
||||||
let unknown_state = ProcessStatus::Unknown(0).to_string();
|
let unknown_state = ProcessStatus::Unknown(0).to_string();
|
||||||
let cpu_usage_unknown_pids: Vec<i32> = process_vector
|
let cpu_usage_unknown_pids: Vec<Pid> = process_vector
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|process| process.process_state.0 == unknown_state)
|
.filter(|process| process.process_state.0 == unknown_state)
|
||||||
.map(|process| process.pid)
|
.map(|process| process.pid)
|
||||||
|
|
Loading…
Reference in a new issue