diff --git a/README.md b/README.md index 0f87c745c..444b8da1f 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Otherwise, here is a little code sample: ```rust use sysinfo::{ Components, ComponentsExt, Disks, NetworkExt, Networks, - NetworksExt, ProcessExt, System, + NetworksExt, System, }; // Please note that we use "new_all" to ensure that all list of diff --git a/examples/simple.rs b/examples/simple.rs index c0884072e..15eae8e7d 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -8,8 +8,8 @@ use std::io::{self, BufRead, Write}; use std::str::FromStr; use sysinfo::Signal::*; use sysinfo::{ - Components, ComponentsExt, CpuExt, Disks, NetworkExt, Networks, NetworksExt, Pid, ProcessExt, - Signal, System, UserExt, Users, UsersExt, + Components, ComponentsExt, CpuExt, Disks, NetworkExt, Networks, NetworksExt, Pid, Signal, + System, UserExt, Users, UsersExt, }; const signals: &[Signal] = &[ diff --git a/md_doc/process.md b/md_doc/process.md deleted file mode 100644 index 0b7f9f7f7..000000000 --- a/md_doc/process.md +++ /dev/null @@ -1,10 +0,0 @@ -Struct containing information of a process. - -## iOS - -This information cannot be retrieved on iOS due to sandboxing. - -## Apple app store - -If you are building a macOS Apple app store, it won't be able -to retrieve this information. diff --git a/md_doc/supported_signals.md b/md_doc/supported_signals.md index ded947927..1b9fdf662 100644 --- a/md_doc/supported_signals.md +++ b/md_doc/supported_signals.md @@ -1,5 +1,5 @@ Returns the list of the supported signals on this system (used by -[`ProcessExt::kill_with`][crate::ProcessExt::kill_with]). +[`Process::kill_with`][crate::Process::kill_with]). ``` use sysinfo::{System, SUPPORTED_SIGNALS}; diff --git a/src/c_interface.rs b/src/c_interface.rs index e0665344f..b99f90359 100644 --- a/src/c_interface.rs +++ b/src/c_interface.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use crate::{CpuExt, Disks, NetworkExt, Networks, NetworksExt, Pid, Process, ProcessExt, System}; +use crate::{CpuExt, Disks, NetworkExt, Networks, NetworksExt, Pid, Process, System}; use libc::{self, c_char, c_float, c_uint, c_void, size_t}; use std::borrow::BorrowMut; use std::ffi::CString; @@ -416,12 +416,12 @@ pub extern "C" fn sysinfo_process_tasks( if let Some(fn_pointer) = fn_pointer { unsafe { let process = process as *const Process; - for (pid, process) in (*process).tasks.iter() { + for (pid, process) in (*process).tasks().iter() { if !fn_pointer(pid.0, process as *const Process as CProcess, data) { break; } } - (*process).tasks.len() as size_t + (*process).tasks().len() as size_t } } else { 0 diff --git a/src/common.rs b/src/common.rs index 9b42bebd0..6446c4044 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,8 +1,8 @@ // Take a look at the license at the top of the repository in the LICENSE file. use crate::{ - Component, Components, ComponentsExt, Cpu, GroupExt, NetworkData, NetworksExt, Process, - ProcessExt, SystemInner, User, UserExt, UsersExt, + Component, Components, ComponentsExt, Cpu, GroupExt, NetworkData, NetworksExt, ProcessInner, + SystemInner, User, UserExt, UsersExt, }; use std::cmp::Ordering; @@ -302,7 +302,7 @@ impl System { /// Returns the process list. /// /// ```no_run - /// use sysinfo::{ProcessExt, System}; + /// use sysinfo::System; /// /// let s = System::new_all(); /// for (pid, process) in s.processes() { @@ -316,7 +316,7 @@ impl System { /// Returns the process corresponding to the given `pid` or `None` if no such process exists. /// /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; + /// use sysinfo::{Pid, System}; /// /// let s = System::new_all(); /// if let Some(process) = s.process(Pid::from(1337)) { @@ -339,7 +339,7 @@ impl System { /// 2. It is not always the exe name. /// /// ```no_run - /// use sysinfo::{ProcessExt, System}; + /// use sysinfo::System; /// /// let s = System::new_all(); /// for process in s.processes_by_name("htop") { @@ -370,7 +370,7 @@ impl System { /// 2. It is not always the exe name. /// /// ```no_run - /// use sysinfo::{ProcessExt, System}; + /// use sysinfo::System; /// /// let s = System::new_all(); /// for process in s.processes_by_exact_name("htop") { @@ -678,6 +678,455 @@ impl System { } } +/// Struct containing information of a process. +/// +/// ## iOS +/// +/// This information cannot be retrieved on iOS due to sandboxing. +/// +/// ## Apple app store +/// +/// If you are building a macOS Apple app store, it won't be able +/// to retrieve this information. +/// +/// ```no_run +/// use sysinfo::{Pid, System}; +/// +/// let s = System::new_all(); +/// if let Some(process) = s.process(Pid::from(1337)) { +/// println!("{}", process.name()); +/// } +/// ``` +pub struct Process { + pub(crate) inner: ProcessInner, +} + +impl Process { + /// Sends [`Signal::Kill`] to the process (which is the only signal supported on all supported + /// platforms by this crate). + /// + /// If you want to send another signal, take a look at [`Process::kill_with`]. + /// + /// To get the list of the supported signals on this system, use + /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS]. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// process.kill(); + /// } + /// ``` + pub fn kill(&self) -> bool { + self.kill_with(Signal::Kill).unwrap_or(false) + } + + /// Sends the given `signal` to the process. If the signal doesn't exist on this platform, + /// it'll do nothing and will return `None`. Otherwise it'll return if the signal was sent + /// successfully. + /// + /// If you just want to kill the process, use [`Process::kill`] directly. + /// + /// To get the list of the supported signals on this system, use + /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS]. + /// + /// ```no_run + /// use sysinfo::{Pid, Signal, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// if process.kill_with(Signal::Kill).is_none() { + /// eprintln!("This signal isn't supported on this platform"); + /// } + /// } + /// ``` + pub fn kill_with(&self, signal: Signal) -> Option { + self.inner.kill_with(signal) + } + + /// Returns the name of the process. + /// + /// **⚠️ Important ⚠️** + /// + /// On **Linux**, there are two things to know about processes' name: + /// 1. It is limited to 15 characters. + /// 2. It is not always the exe name. + /// + /// If you are looking for a specific process, unless you know what you are + /// doing, in most cases it's better to use [`Process::exe`] instead (which + /// can be empty sometimes!). + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{}", process.name()); + /// } + /// ``` + pub fn name(&self) -> &str { + self.inner.name() + } + + /// Returns the command line. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{:?}", process.cmd()); + /// } + /// ``` + pub fn cmd(&self) -> &[String] { + self.inner.cmd() + } + + /// Returns the path to the process. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{}", process.exe().display()); + /// } + /// ``` + /// + /// ### Implementation notes + /// + /// On Linux, this method will return an empty path if there + /// was an error trying to read `/proc//exe`. This can + /// happen, for example, if the permission levels or UID namespaces + /// between the caller and target processes are different. + /// + /// It is also the case that `cmd[0]` is _not_ usually a correct + /// replacement for this. + /// A process [may change its `cmd[0]` value](https://man7.org/linux/man-pages/man5/proc.5.html) + /// freely, making this an untrustworthy source of information. + pub fn exe(&self) -> &Path { + self.inner.exe() + } + + /// Returns the PID of the process. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{}", process.pid()); + /// } + /// ``` + pub fn pid(&self) -> Pid { + self.inner.pid() + } + + /// Returns the environment variables of the process. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{:?}", process.environ()); + /// } + /// ``` + pub fn environ(&self) -> &[String] { + self.inner.environ() + } + + /// Returns the current working directory. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{}", process.cwd().display()); + /// } + /// ``` + pub fn cwd(&self) -> &Path { + self.inner.cwd() + } + + /// Returns the path of the root directory. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{}", process.root().display()); + /// } + /// ``` + pub fn root(&self) -> &Path { + self.inner.root() + } + + /// Returns the memory usage (in bytes). + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{} bytes", process.memory()); + /// } + /// ``` + pub fn memory(&self) -> u64 { + self.inner.memory() + } + + /// Returns the virtual memory usage (in bytes). + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{} bytes", process.virtual_memory()); + /// } + /// ``` + pub fn virtual_memory(&self) -> u64 { + self.inner.virtual_memory() + } + + /// Returns the parent PID. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{:?}", process.parent()); + /// } + /// ``` + pub fn parent(&self) -> Option { + self.inner.parent() + } + + /// Returns the status of the process. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{:?}", process.status()); + /// } + /// ``` + pub fn status(&self) -> ProcessStatus { + self.inner.status() + } + + /// Returns the time where the process was started (in seconds) from epoch. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("Started at {} seconds", process.start_time()); + /// } + /// ``` + pub fn start_time(&self) -> u64 { + self.inner.start_time() + } + + /// Returns for how much time the process has been running (in seconds). + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("Running since {} seconds", process.run_time()); + /// } + /// ``` + pub fn run_time(&self) -> u64 { + self.inner.run_time() + } + + /// Returns the total CPU usage (in %). Notice that it might be bigger than + /// 100 if run on a multi-core machine. + /// + /// If you want a value between 0% and 100%, divide the returned value by + /// the number of CPUs. + /// + /// ⚠️ To start to have accurate CPU usage, a process needs to be refreshed + /// **twice** because CPU usage computation is based on time diff (process + /// time on a given time period divided by total system time on the same + /// time period). + /// + /// ⚠️ If you want accurate CPU usage number, better leave a bit of time + /// between two calls of this method (take a look at + /// [`MINIMUM_CPU_UPDATE_INTERVAL`][crate::MINIMUM_CPU_UPDATE_INTERVAL] for + /// more information). + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// println!("{}%", process.cpu_usage()); + /// } + /// ``` + pub fn cpu_usage(&self) -> f32 { + self.inner.cpu_usage() + } + + /// Returns number of bytes read and written to disk. + /// + /// ⚠️ On Windows and FreeBSD, this method actually returns **ALL** I/O + /// read and written bytes. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let s = System::new_all(); + /// if let Some(process) = s.process(Pid::from(1337)) { + /// let disk_usage = process.disk_usage(); + /// println!("read bytes : new/total => {}/{}", + /// disk_usage.read_bytes, + /// disk_usage.total_read_bytes, + /// ); + /// println!("written bytes: new/total => {}/{}", + /// disk_usage.written_bytes, + /// disk_usage.total_written_bytes, + /// ); + /// } + /// ``` + pub fn disk_usage(&self) -> DiskUsage { + self.inner.disk_usage() + } + + /// Returns the ID of the owner user of this process or `None` if this + /// information couldn't be retrieved. If you want to get the [`User`] from + /// it, take a look at [`UsersExt::get_user_by_id`]. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let mut s = System::new_all(); + /// + /// if let Some(process) = s.process(Pid::from(1337)) { + /// eprintln!("User id for process 1337: {:?}", process.user_id()); + /// } + /// ``` + pub fn user_id(&self) -> Option<&Uid> { + self.inner.user_id() + } + + /// Returns the user ID of the effective owner of this process or `None` if + /// this information couldn't be retrieved. If you want to get the [`User`] + /// from it, take a look at [`UsersExt::get_user_by_id`]. + /// + /// If you run something with `sudo`, the real user ID of the launched + /// process will be the ID of the user you are logged in as but effective + /// user ID will be `0` (i-e root). + /// + /// ⚠️ It always returns `None` on Windows. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let mut s = System::new_all(); + /// + /// if let Some(process) = s.process(Pid::from(1337)) { + /// eprintln!("User id for process 1337: {:?}", process.effective_user_id()); + /// } + /// ``` + pub fn effective_user_id(&self) -> Option<&Uid> { + self.inner.effective_user_id() + } + + /// Returns the process group ID of the process. + /// + /// ⚠️ It always returns `None` on Windows. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let mut s = System::new_all(); + /// + /// if let Some(process) = s.process(Pid::from(1337)) { + /// eprintln!("Group ID for process 1337: {:?}", process.group_id()); + /// } + /// ``` + pub fn group_id(&self) -> Option { + self.inner.group_id() + } + + /// Returns the effective group ID of the process. + /// + /// If you run something with `sudo`, the real group ID of the launched + /// process will be the primary group ID you are logged in as but effective + /// group ID will be `0` (i-e root). + /// + /// ⚠️ It always returns `None` on Windows. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let mut s = System::new_all(); + /// + /// if let Some(process) = s.process(Pid::from(1337)) { + /// eprintln!("User id for process 1337: {:?}", process.effective_group_id()); + /// } + /// ``` + pub fn effective_group_id(&self) -> Option { + self.inner.effective_group_id() + } + + /// Wait for process termination. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let mut s = System::new_all(); + /// + /// if let Some(process) = s.process(Pid::from(1337)) { + /// eprintln!("Waiting for pid 1337"); + /// process.wait(); + /// eprintln!("Pid 1337 exited"); + /// } + /// ``` + pub fn wait(&self) { + self.inner.wait() + } + + /// Returns the session ID for the current process or `None` if it couldn't + /// be retrieved. + /// + /// ⚠️ This information is computed every time this method is called. + /// + /// ```no_run + /// use sysinfo::{Pid, System}; + /// + /// let mut s = System::new_all(); + /// + /// if let Some(process) = s.process(Pid::from(1337)) { + /// eprintln!("Session ID for process 1337: {:?}", process.session_id()); + /// } + /// ``` + pub fn session_id(&self) -> Option { + self.inner.session_id() + } + + /// Tasks run by this process. + /// + /// ⚠️ This method is only available on Linux. + #[cfg(all( + any(target_os = "linux", target_os = "android"), + not(feature = "unknown-ci") + ))] + pub fn tasks(&self) -> &HashMap { + &self.inner.tasks + } +} + /// Trait to have a common conversions for the [`Pid`][crate::Pid] type. /// /// ``` @@ -884,7 +1333,7 @@ assert_eq!(r.", stringify!($name), "().is_some(), false); /// extra computation. /// /// ``` -/// use sysinfo::{ProcessExt, ProcessRefreshKind, System}; +/// use sysinfo::{ProcessRefreshKind, System}; /// /// let mut system = System::new(); /// @@ -1809,10 +2258,10 @@ impl GroupExt for Group { /// Type containing read and written bytes. /// -/// It is returned by [`ProcessExt::disk_usage`][crate::ProcessExt::disk_usage]. +/// It is returned by [`Process::disk_usage`][crate::Process::disk_usage]. /// /// ```no_run -/// use sysinfo::{ProcessExt, System}; +/// use sysinfo::System; /// /// let s = System::new_all(); /// for (pid, process) in s.processes() { diff --git a/src/debug.rs b/src/debug.rs index e3a29c251..137dbc520 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -2,7 +2,7 @@ use crate::{ Component, ComponentExt, Components, Cpu, CpuExt, Disk, Disks, NetworkData, NetworkExt, - Networks, NetworksExt, Process, ProcessExt, System, User, UserExt, Users, + Networks, NetworksExt, Process, System, User, UserExt, Users, }; use std::fmt; diff --git a/src/lib.rs b/src/lib.rs index 708e43a49..fc0040c21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,18 +53,17 @@ cfg_if::cfg_if! { pub use crate::common::{ get_current_pid, CpuRefreshKind, Disk, DiskKind, DiskUsage, Disks, Gid, Group, LoadAvg, - MacAddr, Networks, NetworksIter, Pid, PidExt, ProcessRefreshKind, ProcessStatus, RefreshKind, - Signal, System, Uid, Users, + MacAddr, Networks, NetworksIter, Pid, PidExt, Process, ProcessRefreshKind, ProcessStatus, + RefreshKind, Signal, System, Uid, Users, }; pub use crate::sys::{ - Component, Components, Cpu, NetworkData, Process, User, IS_SUPPORTED, - MINIMUM_CPU_UPDATE_INTERVAL, SUPPORTED_SIGNALS, + Component, Components, Cpu, NetworkData, User, IS_SUPPORTED, MINIMUM_CPU_UPDATE_INTERVAL, + SUPPORTED_SIGNALS, }; -pub(crate) use crate::sys::{DiskInner, DisksInner, SystemInner}; +pub(crate) use crate::sys::{DiskInner, DisksInner, ProcessInner, SystemInner}; pub use crate::traits::{ - ComponentExt, ComponentsExt, CpuExt, GroupExt, NetworkExt, NetworksExt, ProcessExt, UserExt, - UsersExt, + ComponentExt, ComponentsExt, CpuExt, GroupExt, NetworkExt, NetworksExt, UserExt, UsersExt, }; #[cfg(feature = "c-interface")] diff --git a/src/serde.rs b/src/serde.rs index 481a04fa9..2fc7b1ffe 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -3,7 +3,7 @@ use crate::common::PidExt; use crate::{ ComponentExt, CpuExt, DiskKind, DiskUsage, GroupExt, MacAddr, NetworkExt, NetworksExt, - ProcessExt, ProcessStatus, Signal, UserExt, + ProcessStatus, Signal, UserExt, }; use serde::{ser::SerializeStruct, Serialize, Serializer}; use std::ops::Deref; diff --git a/src/system.rs b/src/system.rs index 5983b7f08..bf9f5c5f4 100644 --- a/src/system.rs +++ b/src/system.rs @@ -5,7 +5,7 @@ #[cfg(test)] mod tests { - use crate::{ProcessExt, System}; + use crate::System; #[test] fn test_refresh_system() { @@ -120,7 +120,7 @@ mod tests { #[test] #[ignore] // This test MUST be run on its own to prevent wrong CPU usage measurements. fn test_consecutive_cpu_usage_update() { - use crate::{PidExt, ProcessExt, ProcessRefreshKind, System}; + use crate::{PidExt, ProcessRefreshKind, System}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::Duration; diff --git a/src/traits.rs b/src/traits.rs index 1d139b717..ab44465c1 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -4,383 +4,9 @@ use crate::{ common::{Gid, MacAddr, Uid}, sys::Component, }; -use crate::{DiskUsage, Group, NetworksIter, Pid, ProcessStatus, Signal, User}; +use crate::{Group, NetworksIter, User}; use std::fmt::Debug; -use std::path::Path; - -/// Contains all the methods of the [`Process`][crate::Process] struct. -/// -/// ```no_run -/// use sysinfo::{Pid, ProcessExt, System}; -/// -/// let s = System::new_all(); -/// if let Some(process) = s.process(Pid::from(1337)) { -/// println!("{}", process.name()); -/// } -/// ``` -pub trait ProcessExt: Debug { - /// Sends [`Signal::Kill`] to the process (which is the only signal supported on all supported - /// platforms by this crate). - /// - /// If you want to send another signal, take a look at [`ProcessExt::kill_with`]. - /// - /// To get the list of the supported signals on this system, use - /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS]. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// process.kill(); - /// } - /// ``` - fn kill(&self) -> bool { - self.kill_with(Signal::Kill).unwrap_or(false) - } - - /// Sends the given `signal` to the process. If the signal doesn't exist on this platform, - /// it'll do nothing and will return `None`. Otherwise it'll return if the signal was sent - /// successfully. - /// - /// If you just want to kill the process, use [`ProcessExt::kill`] directly. - /// - /// To get the list of the supported signals on this system, use - /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS]. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, Signal, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// if process.kill_with(Signal::Kill).is_none() { - /// eprintln!("This signal isn't supported on this platform"); - /// } - /// } - /// ``` - fn kill_with(&self, signal: Signal) -> Option; - - /// Returns the name of the process. - /// - /// **⚠️ Important ⚠️** - /// - /// On **Linux**, there are two things to know about processes' name: - /// 1. It is limited to 15 characters. - /// 2. It is not always the exe name. - /// - /// If you are looking for a specific process, unless you know what you are doing, in most - /// cases it's better to use [`ProcessExt::exe`] instead (which can be empty sometimes!). - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{}", process.name()); - /// } - /// ``` - fn name(&self) -> &str; - - /// Returns the command line. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{:?}", process.cmd()); - /// } - /// ``` - fn cmd(&self) -> &[String]; - - /// Returns the path to the process. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{}", process.exe().display()); - /// } - /// ``` - /// - /// ### Implementation notes - /// - /// On Linux, this method will return an empty path if there - /// was an error trying to read `/proc//exe`. This can - /// happen, for example, if the permission levels or UID namespaces - /// between the caller and target processes are different. - /// - /// It is also the case that `cmd[0]` is _not_ usually a correct - /// replacement for this. - /// A process [may change its `cmd[0]` value](https://man7.org/linux/man-pages/man5/proc.5.html) - /// freely, making this an untrustworthy source of information. - fn exe(&self) -> &Path; - - /// Returns the PID of the process. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{}", process.pid()); - /// } - /// ``` - fn pid(&self) -> Pid; - - /// Returns the environment variables of the process. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{:?}", process.environ()); - /// } - /// ``` - fn environ(&self) -> &[String]; - - /// Returns the current working directory. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{}", process.cwd().display()); - /// } - /// ``` - fn cwd(&self) -> &Path; - - /// Returns the path of the root directory. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{}", process.root().display()); - /// } - /// ``` - fn root(&self) -> &Path; - - /// Returns the memory usage (in bytes). - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{} bytes", process.memory()); - /// } - /// ``` - fn memory(&self) -> u64; - - /// Returns the virtual memory usage (in bytes). - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{} bytes", process.virtual_memory()); - /// } - /// ``` - fn virtual_memory(&self) -> u64; - - /// Returns the parent PID. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{:?}", process.parent()); - /// } - /// ``` - fn parent(&self) -> Option; - - /// Returns the status of the process. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{:?}", process.status()); - /// } - /// ``` - fn status(&self) -> ProcessStatus; - - /// Returns the time where the process was started (in seconds) from epoch. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("Started at {} seconds", process.start_time()); - /// } - /// ``` - fn start_time(&self) -> u64; - - /// Returns for how much time the process has been running (in seconds). - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("Running since {} seconds", process.run_time()); - /// } - /// ``` - fn run_time(&self) -> u64; - - /// Returns the total CPU usage (in %). Notice that it might be bigger than 100 if run on a - /// multi-core machine. - /// - /// If you want a value between 0% and 100%, divide the returned value by the number of CPUs. - /// - /// ⚠️ To start to have accurate CPU usage, a process needs to be refreshed **twice** because - /// CPU usage computation is based on time diff (process time on a given time period divided by - /// total system time on the same time period). - /// - /// ⚠️ If you want accurate CPU usage number, better leave a bit of time - /// between two calls of this method (take a look at - /// [`MINIMUM_CPU_UPDATE_INTERVAL`][crate::MINIMUM_CPU_UPDATE_INTERVAL] for more information). - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// println!("{}%", process.cpu_usage()); - /// } - /// ``` - fn cpu_usage(&self) -> f32; - - /// Returns number of bytes read and written to disk. - /// - /// ⚠️ On Windows and FreeBSD, this method actually returns **ALL** I/O read and written bytes. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let s = System::new_all(); - /// if let Some(process) = s.process(Pid::from(1337)) { - /// let disk_usage = process.disk_usage(); - /// println!("read bytes : new/total => {}/{}", - /// disk_usage.read_bytes, - /// disk_usage.total_read_bytes, - /// ); - /// println!("written bytes: new/total => {}/{}", - /// disk_usage.written_bytes, - /// disk_usage.total_written_bytes, - /// ); - /// } - /// ``` - fn disk_usage(&self) -> DiskUsage; - - /// Returns the ID of the owner user of this process or `None` if this information couldn't - /// be retrieved. If you want to get the [`User`] from it, take a look at - /// [`UsersExt::get_user_by_id`]. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let mut s = System::new_all(); - /// - /// if let Some(process) = s.process(Pid::from(1337)) { - /// eprintln!("User id for process 1337: {:?}", process.user_id()); - /// } - /// ``` - fn user_id(&self) -> Option<&Uid>; - - /// Returns the user ID of the effective owner of this process or `None` if this information - /// couldn't be retrieved. If you want to get the [`User`] from it, take a look at - /// [`UsersExt::get_user_by_id`]. - /// - /// If you run something with `sudo`, the real user ID of the launched process will be the ID of - /// the user you are logged in as but effective user ID will be `0` (i-e root). - /// - /// ⚠️ It always returns `None` on Windows. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let mut s = System::new_all(); - /// - /// if let Some(process) = s.process(Pid::from(1337)) { - /// eprintln!("User id for process 1337: {:?}", process.effective_user_id()); - /// } - /// ``` - fn effective_user_id(&self) -> Option<&Uid>; - - /// Returns the process group ID of the process. - /// - /// ⚠️ It always returns `None` on Windows. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let mut s = System::new_all(); - /// - /// if let Some(process) = s.process(Pid::from(1337)) { - /// eprintln!("Group ID for process 1337: {:?}", process.group_id()); - /// } - /// ``` - fn group_id(&self) -> Option; - - /// Returns the effective group ID of the process. - /// - /// If you run something with `sudo`, the real group ID of the launched process will be the - /// primary group ID you are logged in as but effective group ID will be `0` (i-e root). - /// - /// ⚠️ It always returns `None` on Windows. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let mut s = System::new_all(); - /// - /// if let Some(process) = s.process(Pid::from(1337)) { - /// eprintln!("User id for process 1337: {:?}", process.effective_group_id()); - /// } - /// ``` - fn effective_group_id(&self) -> Option; - - /// Wait for process termination. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let mut s = System::new_all(); - /// - /// if let Some(process) = s.process(Pid::from(1337)) { - /// eprintln!("Waiting for pid 1337"); - /// process.wait(); - /// eprintln!("Pid 1337 exited"); - /// } - /// ``` - fn wait(&self); - - /// Returns the session ID for the current process or `None` if it couldn't be retrieved. - /// - /// ⚠️ This information is computed every time this method is called. - /// - /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System}; - /// - /// let mut s = System::new_all(); - /// - /// if let Some(process) = s.process(Pid::from(1337)) { - /// eprintln!("Session ID for process 1337: {:?}", process.session_id()); - /// } - /// ``` - fn session_id(&self) -> Option; -} /// Contains all the methods of the [`Cpu`][crate::Cpu] struct. /// @@ -1135,7 +761,7 @@ pub trait UsersExt: Debug { /// Full example: /// /// ```no_run - /// use sysinfo::{Pid, ProcessExt, System, Users, UsersExt}; + /// use sysinfo::{Pid, System, Users, UsersExt}; /// /// let mut s = System::new_all(); /// let mut users = Users::new(); diff --git a/src/unix/apple/app_store/process.rs b/src/unix/apple/app_store/process.rs index 033075bfa..4ac94d8bd 100644 --- a/src/unix/apple/app_store/process.rs +++ b/src/unix/apple/app_store/process.rs @@ -2,95 +2,94 @@ use std::path::Path; -use crate::{DiskUsage, Gid, Pid, ProcessExt, ProcessStatus, Signal, Uid}; +use crate::{DiskUsage, Gid, Pid, ProcessStatus, Signal, Uid}; -#[doc = include_str!("../../../../md_doc/process.md")] -pub struct Process; +pub(crate) struct ProcessInner; -impl ProcessExt for Process { - fn kill_with(&self, _signal: Signal) -> Option { +impl ProcessInner { + pub(crate) fn kill_with(&self, _signal: Signal) -> Option { None } - fn name(&self) -> &str { + pub(crate) fn name(&self) -> &str { "" } - fn cmd(&self) -> &[String] { + pub(crate) fn cmd(&self) -> &[String] { &[] } - fn exe(&self) -> &Path { + pub(crate) fn exe(&self) -> &Path { Path::new("/") } - fn pid(&self) -> Pid { + pub(crate) fn pid(&self) -> Pid { Pid(0) } - fn environ(&self) -> &[String] { + pub(crate) fn environ(&self) -> &[String] { &[] } - fn cwd(&self) -> &Path { + pub(crate) fn cwd(&self) -> &Path { Path::new("/") } - fn root(&self) -> &Path { + pub(crate) fn root(&self) -> &Path { Path::new("/") } - fn memory(&self) -> u64 { + pub(crate) fn memory(&self) -> u64 { 0 } - fn virtual_memory(&self) -> u64 { + pub(crate) fn virtual_memory(&self) -> u64 { 0 } - fn parent(&self) -> Option { + pub(crate) fn parent(&self) -> Option { None } - fn status(&self) -> ProcessStatus { + pub(crate) fn status(&self) -> ProcessStatus { ProcessStatus::Unknown(0) } - fn start_time(&self) -> u64 { + pub(crate) fn start_time(&self) -> u64 { 0 } - fn run_time(&self) -> u64 { + pub(crate) fn run_time(&self) -> u64 { 0 } - fn cpu_usage(&self) -> f32 { + pub(crate) fn cpu_usage(&self) -> f32 { 0.0 } - fn disk_usage(&self) -> DiskUsage { + pub(crate) fn disk_usage(&self) -> DiskUsage { DiskUsage::default() } - fn user_id(&self) -> Option<&Uid> { + pub(crate) fn user_id(&self) -> Option<&Uid> { None } - fn effective_user_id(&self) -> Option<&Uid> { + pub(crate) fn effective_user_id(&self) -> Option<&Uid> { None } - fn group_id(&self) -> Option { + pub(crate) fn group_id(&self) -> Option { None } - fn effective_group_id(&self) -> Option { + pub(crate) fn effective_group_id(&self) -> Option { None } - fn wait(&self) {} + pub(crate) fn wait(&self) {} - fn session_id(&self) -> Option { + pub(crate) fn session_id(&self) -> Option { None } } diff --git a/src/unix/apple/macos/process.rs b/src/unix/apple/macos/process.rs index 259af9776..cad8c05d8 100644 --- a/src/unix/apple/macos/process.rs +++ b/src/unix/apple/macos/process.rs @@ -9,13 +9,12 @@ use std::borrow::Borrow; use libc::{c_int, c_void, kill, size_t}; -use crate::{DiskUsage, Gid, Pid, ProcessExt, ProcessRefreshKind, ProcessStatus, Signal, Uid}; +use crate::{DiskUsage, Gid, Pid, Process, ProcessRefreshKind, ProcessStatus, Signal, Uid}; use crate::sys::process::ThreadStatus; use crate::sys::system::Wrap; -#[doc = include_str!("../../../../md_doc/process.md")] -pub struct Process { +pub(crate) struct ProcessInner { pub(crate) name: String, pub(crate) cmd: Vec, pub(crate) exe: PathBuf, @@ -48,9 +47,9 @@ pub struct Process { pub(crate) written_bytes: u64, } -impl Process { - pub(crate) fn new_empty(pid: Pid, exe: PathBuf, name: String, cwd: PathBuf) -> Process { - Process { +impl ProcessInner { + pub(crate) fn new_empty(pid: Pid, exe: PathBuf, name: String, cwd: PathBuf) -> Self { + Self { name, pid, parent: None, @@ -80,8 +79,8 @@ impl Process { } } - pub(crate) fn new(pid: Pid, parent: Option, start_time: u64, run_time: u64) -> Process { - Process { + pub(crate) fn new(pid: Pid, parent: Option, start_time: u64, run_time: u64) -> Self { + Self { name: String::new(), pid, parent, @@ -110,55 +109,53 @@ impl Process { written_bytes: 0, } } -} -impl ProcessExt for Process { - fn kill_with(&self, signal: Signal) -> Option { + pub(crate) fn kill_with(&self, signal: Signal) -> Option { let c_signal = crate::sys::convert_signal(signal)?; unsafe { Some(kill(self.pid.0, c_signal) == 0) } } - fn name(&self) -> &str { + pub(crate) fn name(&self) -> &str { &self.name } - fn cmd(&self) -> &[String] { + pub(crate) fn cmd(&self) -> &[String] { &self.cmd } - fn exe(&self) -> &Path { + pub(crate) fn exe(&self) -> &Path { self.exe.as_path() } - fn pid(&self) -> Pid { + pub(crate) fn pid(&self) -> Pid { self.pid } - fn environ(&self) -> &[String] { + pub(crate) fn environ(&self) -> &[String] { &self.environ } - fn cwd(&self) -> &Path { + pub(crate) fn cwd(&self) -> &Path { self.cwd.as_path() } - fn root(&self) -> &Path { + pub(crate) fn root(&self) -> &Path { self.root.as_path() } - fn memory(&self) -> u64 { + pub(crate) fn memory(&self) -> u64 { self.memory } - fn virtual_memory(&self) -> u64 { + pub(crate) fn virtual_memory(&self) -> u64 { self.virtual_memory } - fn parent(&self) -> Option { + pub(crate) fn parent(&self) -> Option { self.parent } - fn status(&self) -> ProcessStatus { + pub(crate) fn status(&self) -> ProcessStatus { // If the status is `Run`, then it's very likely wrong so we instead // return a `ProcessStatus` converted from the `ThreadStatus`. if self.process_status == ProcessStatus::Run { @@ -169,19 +166,19 @@ impl ProcessExt for Process { self.process_status } - fn start_time(&self) -> u64 { + pub(crate) fn start_time(&self) -> u64 { self.start_time } - fn run_time(&self) -> u64 { + pub(crate) fn run_time(&self) -> u64 { self.run_time } - fn cpu_usage(&self) -> f32 { + pub(crate) fn cpu_usage(&self) -> f32 { self.cpu_usage } - fn disk_usage(&self) -> DiskUsage { + pub(crate) fn disk_usage(&self) -> DiskUsage { DiskUsage { read_bytes: self.read_bytes.saturating_sub(self.old_read_bytes), total_read_bytes: self.read_bytes, @@ -190,23 +187,23 @@ impl ProcessExt for Process { } } - fn user_id(&self) -> Option<&Uid> { + pub(crate) fn user_id(&self) -> Option<&Uid> { self.user_id.as_ref() } - fn effective_user_id(&self) -> Option<&Uid> { + pub(crate) fn effective_user_id(&self) -> Option<&Uid> { self.effective_user_id.as_ref() } - fn group_id(&self) -> Option { + pub(crate) fn group_id(&self) -> Option { self.group_id } - fn effective_group_id(&self) -> Option { + pub(crate) fn effective_group_id(&self) -> Option { self.effective_group_id } - fn wait(&self) { + pub(crate) fn wait(&self) { let mut status = 0; // attempt waiting unsafe { @@ -220,7 +217,7 @@ impl ProcessExt for Process { } } - fn session_id(&self) -> Option { + pub(crate) fn session_id(&self) -> Option { unsafe { let session_id = libc::getsid(self.pid.0); if session_id < 0 { @@ -234,7 +231,7 @@ impl ProcessExt for Process { #[allow(deprecated)] // Because of libc::mach_absolute_time. pub(crate) fn compute_cpu_usage( - p: &mut Process, + p: &mut ProcessInner, task_info: libc::proc_taskinfo, system_time: u64, user_time: u64, @@ -394,7 +391,9 @@ unsafe fn create_new_process( .and_then(|x| x.to_str()) .unwrap_or("") .to_owned(); - return Ok(Some(Process::new_empty(pid, exe, name, cwd))); + return Ok(Some(Process { + inner: ProcessInner::new_empty(pid, exe, name, cwd), + })); } _ => {} } @@ -529,7 +528,7 @@ unsafe fn create_new_process( } else { get_environ(ptr, cp, size, PathBuf::new(), do_get_env_path) }; - let mut p = Process::new(pid, parent, start_time, run_time); + let mut p = ProcessInner::new(pid, parent, start_time, run_time); p.exe = exe; p.name = name; @@ -539,7 +538,7 @@ unsafe fn create_new_process( p.root = root; p } else { - Process::new(pid, parent, start_time, run_time) + ProcessInner::new(pid, parent, start_time, run_time) }; let task_info = get_task_info(pid); @@ -555,7 +554,7 @@ unsafe fn create_new_process( if refresh_kind.disk_usage() { update_proc_disk_activity(&mut p); } - Ok(Some(p)) + Ok(Some(Process { inner: p })) } pub(crate) fn update_process( @@ -569,6 +568,7 @@ pub(crate) fn update_process( ) -> Result, ()> { unsafe { if let Some(ref mut p) = (*wrap.0.get()).get_mut(&pid) { + let p = &mut p.inner; if p.memory == 0 { // We don't have access to this process' information. return if check_if_pid_is_alive(pid, check_if_alive) { @@ -627,7 +627,7 @@ pub(crate) fn update_process( } } -fn update_proc_disk_activity(p: &mut Process) { +fn update_proc_disk_activity(p: &mut ProcessInner) { p.old_read_bytes = p.read_bytes; p.old_written_bytes = p.written_bytes; diff --git a/src/unix/apple/mod.rs b/src/unix/apple/mod.rs index f90878204..bd5ca29f1 100644 --- a/src/unix/apple/mod.rs +++ b/src/unix/apple/mod.rs @@ -28,7 +28,7 @@ pub use self::component::{Component, Components}; pub use self::cpu::Cpu; pub(crate) use self::disk::DiskInner; pub use self::network::NetworkData; -pub use self::process::Process; +pub(crate) use self::process::ProcessInner; pub(crate) use self::system::SystemInner; pub(crate) use crate::unix::users::get_users; pub use crate::unix::users::User; diff --git a/src/unix/apple/process.rs b/src/unix/apple/process.rs index ba2912bd3..1a251da57 100644 --- a/src/unix/apple/process.rs +++ b/src/unix/apple/process.rs @@ -2,7 +2,7 @@ use std::fmt; -pub use crate::sys::inner::process::*; +pub(crate) use crate::sys::inner::process::*; use crate::ProcessStatus; #[doc(hidden)] diff --git a/src/unix/apple/system.rs b/src/unix/apple/system.rs index e775424ac..04d25fd93 100644 --- a/src/unix/apple/system.rs +++ b/src/unix/apple/system.rs @@ -1,13 +1,11 @@ // Take a look at the license at the top of the repository in the LICENSE file. use crate::sys::cpu::*; +#[cfg(all(target_os = "macos", not(feature = "apple-sandbox")))] use crate::sys::process::*; use crate::sys::utils::{get_sys_value, get_sys_value_by_name}; -use crate::{CpuRefreshKind, LoadAvg, Pid, ProcessRefreshKind}; - -#[cfg(all(target_os = "macos", not(feature = "apple-sandbox")))] -use crate::ProcessExt; +use crate::{CpuRefreshKind, LoadAvg, Pid, Process, ProcessRefreshKind}; use std::cell::UnsafeCell; use std::collections::HashMap; @@ -210,7 +208,7 @@ impl SystemInner { self.process_list.insert(entry.pid(), entry); }); self.process_list - .retain(|_, proc_| std::mem::replace(&mut proc_.updated, false)); + .retain(|_, proc_| std::mem::replace(&mut proc_.inner.updated, false)); } } diff --git a/src/unix/freebsd/mod.rs b/src/unix/freebsd/mod.rs index 71fc24737..6a0de4bd7 100644 --- a/src/unix/freebsd/mod.rs +++ b/src/unix/freebsd/mod.rs @@ -12,7 +12,7 @@ pub use self::component::{Component, Components}; pub use self::cpu::Cpu; pub(crate) use self::disk::DiskInner; pub use self::network::NetworkData; -pub use self::process::Process; +pub(crate) use self::process::ProcessInner; pub(crate) use self::system::SystemInner; pub(crate) use crate::unix::users::get_users; pub use crate::unix::users::User; diff --git a/src/unix/freebsd/process.rs b/src/unix/freebsd/process.rs index 394ebf4f6..e01a3714d 100644 --- a/src/unix/freebsd/process.rs +++ b/src/unix/freebsd/process.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use crate::{DiskUsage, Gid, Pid, ProcessExt, ProcessRefreshKind, ProcessStatus, Signal, Uid}; +use crate::{DiskUsage, Gid, Pid, Process, ProcessRefreshKind, ProcessStatus, Signal, Uid}; use std::fmt; use std::path::{Path, PathBuf}; @@ -40,8 +40,7 @@ impl fmt::Display for ProcessStatus { } } -#[doc = include_str!("../../../md_doc/process.md")] -pub struct Process { +pub(crate) struct ProcessInner { pub(crate) name: String, pub(crate) cmd: Vec, pub(crate) exe: PathBuf, @@ -67,69 +66,69 @@ pub struct Process { old_written_bytes: u64, } -impl ProcessExt for Process { - fn kill_with(&self, signal: Signal) -> Option { +impl ProcessInner { + pub(crate) fn kill_with(&self, signal: Signal) -> Option { let c_signal = crate::sys::convert_signal(signal)?; unsafe { Some(libc::kill(self.pid.0, c_signal) == 0) } } - fn name(&self) -> &str { + pub(crate) fn name(&self) -> &str { &self.name } - fn cmd(&self) -> &[String] { + pub(crate) fn cmd(&self) -> &[String] { &self.cmd } - fn exe(&self) -> &Path { + pub(crate) fn exe(&self) -> &Path { self.exe.as_path() } - fn pid(&self) -> Pid { + pub(crate) fn pid(&self) -> Pid { self.pid } - fn environ(&self) -> &[String] { + pub(crate) fn environ(&self) -> &[String] { &self.environ } - fn cwd(&self) -> &Path { + pub(crate) fn cwd(&self) -> &Path { self.cwd.as_path() } - fn root(&self) -> &Path { + pub(crate) fn root(&self) -> &Path { self.root.as_path() } - fn memory(&self) -> u64 { + pub(crate) fn memory(&self) -> u64 { self.memory } - fn virtual_memory(&self) -> u64 { + pub(crate) fn virtual_memory(&self) -> u64 { self.virtual_memory } - fn parent(&self) -> Option { + pub(crate) fn parent(&self) -> Option { self.parent } - fn status(&self) -> ProcessStatus { + pub(crate) fn status(&self) -> ProcessStatus { self.status } - fn start_time(&self) -> u64 { + pub(crate) fn start_time(&self) -> u64 { self.start_time } - fn run_time(&self) -> u64 { + pub(crate) fn run_time(&self) -> u64 { self.run_time } - fn cpu_usage(&self) -> f32 { + pub(crate) fn cpu_usage(&self) -> f32 { self.cpu_usage } - fn disk_usage(&self) -> DiskUsage { + pub(crate) fn disk_usage(&self) -> DiskUsage { DiskUsage { written_bytes: self.written_bytes.saturating_sub(self.old_written_bytes), total_written_bytes: self.written_bytes, @@ -138,23 +137,23 @@ impl ProcessExt for Process { } } - fn user_id(&self) -> Option<&Uid> { + pub(crate) fn user_id(&self) -> Option<&Uid> { Some(&self.user_id) } - fn effective_user_id(&self) -> Option<&Uid> { + pub(crate) fn effective_user_id(&self) -> Option<&Uid> { Some(&self.effective_user_id) } - fn group_id(&self) -> Option { + pub(crate) fn group_id(&self) -> Option { Some(self.group_id) } - fn effective_group_id(&self) -> Option { + pub(crate) fn effective_group_id(&self) -> Option { Some(self.effective_group_id) } - fn wait(&self) { + pub(crate) fn wait(&self) { let mut status = 0; // attempt waiting unsafe { @@ -168,7 +167,7 @@ impl ProcessExt for Process { } } - fn session_id(&self) -> Option { + pub(crate) fn session_id(&self) -> Option { unsafe { let session_id = libc::getsid(self.pid.0); if session_id < 0 { @@ -216,6 +215,7 @@ pub(crate) unsafe fn get_process_data( let start_time = kproc.ki_start.tv_sec as u64; if let Some(proc_) = (*wrap.0.get()).get_mut(&Pid(kproc.ki_pid)) { + let mut proc_ = &mut proc_.inner; proc_.updated = true; // If the `start_time` we just got is different from the one stored, it means it's not the // same process. @@ -266,33 +266,35 @@ pub(crate) unsafe fn get_process_data( // .unwrap_or_else(PathBuf::new); Ok(Some(Process { - pid: Pid(kproc.ki_pid), - parent, - user_id: Uid(kproc.ki_ruid), - effective_user_id: Uid(kproc.ki_uid), - group_id: Gid(kproc.ki_rgid), - effective_group_id: Gid(kproc.ki_svgid), - start_time, - run_time: now.saturating_sub(start_time), - cpu_usage, - virtual_memory, - memory, - // procstat_getfiles - cwd: PathBuf::new(), - exe: exe.into(), - // kvm_getargv isn't thread-safe so we get it in the main thread. - name: String::new(), - // kvm_getargv isn't thread-safe so we get it in the main thread. - cmd: Vec::new(), - // kvm_getargv isn't thread-safe so we get it in the main thread. - root: PathBuf::new(), - // kvm_getenvv isn't thread-safe so we get it in the main thread. - environ: Vec::new(), - status, - read_bytes: kproc.ki_rusage.ru_inblock as _, - old_read_bytes: 0, - written_bytes: kproc.ki_rusage.ru_oublock as _, - old_written_bytes: 0, - updated: false, + inner: ProcessInner { + pid: Pid(kproc.ki_pid), + parent, + user_id: Uid(kproc.ki_ruid), + effective_user_id: Uid(kproc.ki_uid), + group_id: Gid(kproc.ki_rgid), + effective_group_id: Gid(kproc.ki_svgid), + start_time, + run_time: now.saturating_sub(start_time), + cpu_usage, + virtual_memory, + memory, + // procstat_getfiles + cwd: PathBuf::new(), + exe: exe.into(), + // kvm_getargv isn't thread-safe so we get it in the main thread. + name: String::new(), + // kvm_getargv isn't thread-safe so we get it in the main thread. + cmd: Vec::new(), + // kvm_getargv isn't thread-safe so we get it in the main thread. + root: PathBuf::new(), + // kvm_getenvv isn't thread-safe so we get it in the main thread. + environ: Vec::new(), + status, + read_bytes: kproc.ki_rusage.ru_inblock as _, + old_read_bytes: 0, + written_bytes: kproc.ki_rusage.ru_oublock as _, + old_written_bytes: 0, + updated: false, + }, })) } diff --git a/src/unix/freebsd/system.rs b/src/unix/freebsd/system.rs index 23dd13e27..3292dbedb 100644 --- a/src/unix/freebsd/system.rs +++ b/src/unix/freebsd/system.rs @@ -1,9 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use crate::{ - sys::{Cpu, Process}, - CpuRefreshKind, LoadAvg, Pid, ProcessRefreshKind, -}; +use crate::{sys::Cpu, CpuRefreshKind, LoadAvg, Pid, Process, ProcessInner, ProcessRefreshKind}; use std::cell::UnsafeCell; use std::collections::HashMap; @@ -266,7 +263,7 @@ impl SystemInner { // We remove all processes that don't exist anymore. self.process_list - .retain(|_, v| std::mem::replace(&mut v.updated, false)); + .retain(|_, v| std::mem::replace(&mut v.inner.updated, false)); for (kproc, proc_) in procs { self.add_missing_proc_info(kd, kproc, proc_); @@ -279,28 +276,31 @@ impl SystemInner { kproc: &libc::kinfo_proc, mut proc_: Process, ) { - proc_.cmd = from_cstr_array(libc::kvm_getargv(kd, kproc, 0) as _); - self.system_info.get_proc_missing_info(kproc, &mut proc_); - if !proc_.cmd.is_empty() { - // First, we try to retrieve the name from the command line. - let p = Path::new(&proc_.cmd[0]); - if let Some(name) = p.file_name().and_then(|s| s.to_str()) { - proc_.name = name.to_owned(); - } - if proc_.root.as_os_str().is_empty() { - if let Some(parent) = p.parent() { - proc_.root = parent.to_path_buf(); + { + let mut proc_inner = &mut proc_.inner; + proc_inner.cmd = from_cstr_array(libc::kvm_getargv(kd, kproc, 0) as _); + self.system_info.get_proc_missing_info(kproc, proc_inner); + if !proc_inner.cmd.is_empty() { + // First, we try to retrieve the name from the command line. + let p = Path::new(&proc_inner.cmd[0]); + if let Some(name) = p.file_name().and_then(|s| s.to_str()) { + proc_inner.name = name.to_owned(); + } + if proc_inner.root.as_os_str().is_empty() { + if let Some(parent) = p.parent() { + proc_inner.root = parent.to_path_buf(); + } } } + if proc_inner.name.is_empty() { + // The name can be cut short because the `ki_comm` field size is limited, + // which is why we prefer to get the name from the command line as much as + // possible. + proc_inner.name = c_buf_to_string(&kproc.ki_comm).unwrap_or_default(); + } + proc_inner.environ = from_cstr_array(libc::kvm_getenvv(kd, kproc, 0) as _); } - if proc_.name.is_empty() { - // The name can be cut short because the `ki_comm` field size is limited, - // which is why we prefer to get the name from the command line as much as - // possible. - proc_.name = c_buf_to_string(&kproc.ki_comm).unwrap_or_default(); - } - proc_.environ = from_cstr_array(libc::kvm_getenvv(kd, kproc, 0) as _); - self.process_list.insert(proc_.pid, proc_); + self.process_list.insert(proc_.inner.pid, proc_); } } @@ -543,7 +543,7 @@ impl SystemInfo { } #[allow(clippy::collapsible_if)] // I keep as is for readability reasons. - unsafe fn get_proc_missing_info(&mut self, kproc: &libc::kinfo_proc, proc_: &mut Process) { + unsafe fn get_proc_missing_info(&mut self, kproc: &libc::kinfo_proc, proc_: &mut ProcessInner) { if self.procstat.is_null() { self.procstat = libc::procstat_open_sysctl(); } diff --git a/src/unix/linux/mod.rs b/src/unix/linux/mod.rs index 4c63193ce..bd98b0fc8 100644 --- a/src/unix/linux/mod.rs +++ b/src/unix/linux/mod.rs @@ -12,7 +12,7 @@ pub use self::component::{Component, Components}; pub use self::cpu::Cpu; pub(crate) use self::disk::DiskInner; pub use self::network::NetworkData; -pub use self::process::Process; +pub(crate) use self::process::ProcessInner; pub(crate) use self::system::SystemInner; pub(crate) use crate::unix::users::get_users; pub use crate::unix::users::User; diff --git a/src/unix/linux/process.rs b/src/unix/linux/process.rs index 3ca7873f5..1b13b2084 100644 --- a/src/unix/linux/process.rs +++ b/src/unix/linux/process.rs @@ -15,7 +15,7 @@ use crate::sys::utils::{ get_all_data, get_all_data_from_file, realpath, FileCounter, PathHandler, PathPush, }; use crate::utils::into_iter; -use crate::{DiskUsage, Gid, Pid, ProcessExt, ProcessRefreshKind, ProcessStatus, Signal, Uid}; +use crate::{DiskUsage, Gid, Pid, Process, ProcessRefreshKind, ProcessStatus, Signal, Uid}; #[doc(hidden)] impl From for ProcessStatus { @@ -56,8 +56,7 @@ impl fmt::Display for ProcessStatus { } } -#[doc = include_str!("../../../md_doc/process.md")] -pub struct Process { +pub(crate) struct ProcessInner { pub(crate) name: String, pub(crate) cmd: Vec, pub(crate) exe: PathBuf, @@ -82,8 +81,7 @@ pub struct Process { group_id: Option, effective_group_id: Option, pub(crate) status: ProcessStatus, - /// Tasks run by this process. - pub tasks: HashMap, + pub(crate) tasks: HashMap, pub(crate) stat_file: Option, old_read_bytes: u64, old_written_bytes: u64, @@ -91,9 +89,9 @@ pub struct Process { written_bytes: u64, } -impl Process { - pub(crate) fn new(pid: Pid) -> Process { - Process { +impl ProcessInner { + pub(crate) fn new(pid: Pid) -> Self { + Self { name: String::with_capacity(20), pid, parent: None, @@ -130,71 +128,69 @@ impl Process { written_bytes: 0, } } -} -impl ProcessExt for Process { - fn kill_with(&self, signal: Signal) -> Option { + pub(crate) fn kill_with(&self, signal: Signal) -> Option { let c_signal = crate::sys::convert_signal(signal)?; unsafe { Some(kill(self.pid.0, c_signal) == 0) } } - fn name(&self) -> &str { + pub(crate) fn name(&self) -> &str { &self.name } - fn cmd(&self) -> &[String] { + pub(crate) fn cmd(&self) -> &[String] { &self.cmd } - fn exe(&self) -> &Path { + pub(crate) fn exe(&self) -> &Path { self.exe.as_path() } - fn pid(&self) -> Pid { + pub(crate) fn pid(&self) -> Pid { self.pid } - fn environ(&self) -> &[String] { + pub(crate) fn environ(&self) -> &[String] { &self.environ } - fn cwd(&self) -> &Path { + pub(crate) fn cwd(&self) -> &Path { self.cwd.as_path() } - fn root(&self) -> &Path { + pub(crate) fn root(&self) -> &Path { self.root.as_path() } - fn memory(&self) -> u64 { + pub(crate) fn memory(&self) -> u64 { self.memory } - fn virtual_memory(&self) -> u64 { + pub(crate) fn virtual_memory(&self) -> u64 { self.virtual_memory } - fn parent(&self) -> Option { + pub(crate) fn parent(&self) -> Option { self.parent } - fn status(&self) -> ProcessStatus { + pub(crate) fn status(&self) -> ProcessStatus { self.status } - fn start_time(&self) -> u64 { + pub(crate) fn start_time(&self) -> u64 { self.start_time } - fn run_time(&self) -> u64 { + pub(crate) fn run_time(&self) -> u64 { self.run_time } - fn cpu_usage(&self) -> f32 { + pub(crate) fn cpu_usage(&self) -> f32 { self.cpu_usage } - fn disk_usage(&self) -> DiskUsage { + pub(crate) fn disk_usage(&self) -> DiskUsage { DiskUsage { written_bytes: self.written_bytes.saturating_sub(self.old_written_bytes), total_written_bytes: self.written_bytes, @@ -203,23 +199,23 @@ impl ProcessExt for Process { } } - fn user_id(&self) -> Option<&Uid> { + pub(crate) fn user_id(&self) -> Option<&Uid> { self.user_id.as_ref() } - fn effective_user_id(&self) -> Option<&Uid> { + pub(crate) fn effective_user_id(&self) -> Option<&Uid> { self.effective_user_id.as_ref() } - fn group_id(&self) -> Option { + pub(crate) fn group_id(&self) -> Option { self.group_id } - fn effective_group_id(&self) -> Option { + pub(crate) fn effective_group_id(&self) -> Option { self.effective_group_id } - fn wait(&self) { + pub(crate) fn wait(&self) { let mut status = 0; // attempt waiting unsafe { @@ -233,7 +229,7 @@ impl ProcessExt for Process { } } - fn session_id(&self) -> Option { + pub(crate) fn session_id(&self) -> Option { unsafe { let session_id = libc::getsid(self.pid.0); if session_id < 0 { @@ -245,7 +241,7 @@ impl ProcessExt for Process { } } -pub(crate) fn compute_cpu_usage(p: &mut Process, total_time: f32, max_value: f32) { +pub(crate) fn compute_cpu_usage(p: &mut ProcessInner, total_time: f32, max_value: f32) { // First time updating the values without reference, wait for a second cycle to update cpu_usage if p.old_utime == 0 && p.old_stime == 0 { return; @@ -262,18 +258,18 @@ pub(crate) fn compute_cpu_usage(p: &mut Process, total_time: f32, max_value: f32 .min(max_value); for task in p.tasks.values_mut() { - compute_cpu_usage(task, total_time, max_value); + compute_cpu_usage(&mut task.inner, total_time, max_value); } } -pub(crate) fn unset_updated(p: &mut Process) { +pub(crate) fn unset_updated(p: &mut ProcessInner) { p.updated = false; for task in p.tasks.values_mut() { - unset_updated(task); + unset_updated(&mut task.inner); } } -pub(crate) fn set_time(p: &mut Process, utime: u64, stime: u64) { +pub(crate) fn set_time(p: &mut ProcessInner, utime: u64, stime: u64) { p.old_utime = p.utime; p.old_stime = p.stime; p.utime = utime; @@ -281,7 +277,7 @@ pub(crate) fn set_time(p: &mut Process, utime: u64, stime: u64) { p.updated = true; } -pub(crate) fn update_process_disk_activity(p: &mut Process, path: &Path) { +pub(crate) fn update_process_disk_activity(p: &mut ProcessInner, path: &Path) { let data = match get_all_data(path.join("io"), 16_384) { Ok(d) => d, Err(_) => return, @@ -341,7 +337,7 @@ fn _get_stat_data(path: &Path, stat_file: &mut Option) -> Result(p: &mut Process, path: &mut P) { +fn refresh_user_group_ids(p: &mut ProcessInner, path: &mut P) { if let Some(((user_id, effective_user_id), (group_id, effective_group_id))) = get_uid_and_gid(path.join("status")) { @@ -362,14 +358,14 @@ fn refresh_user_group_ids(p: &mut Process, path: &mut P) { fn retrieve_all_new_process_info( pid: Pid, - proc_list: &Process, + proc_list: &ProcessInner, parts: &[&str], path: &Path, info: &SystemInfo, refresh_kind: ProcessRefreshKind, uptime: u64, ) -> Process { - let mut p = Process::new(pid); + let mut p = ProcessInner::new(pid); let mut tmp = PathHandler::new(path); let name = parts[1]; @@ -424,12 +420,12 @@ fn retrieve_all_new_process_info( if refresh_kind.disk_usage() { update_process_disk_activity(&mut p, path); } - p + Process { inner: p } } pub(crate) fn _get_process_data( path: &Path, - proc_list: &mut Process, + proc_list: &mut ProcessInner, pid: Pid, uptime: u64, info: &SystemInfo, @@ -450,6 +446,7 @@ pub(crate) fn _get_process_data( let data; let parts = if let Some(ref mut entry) = proc_list.tasks.get_mut(&pid) { + let entry = &mut entry.inner; data = if let Some(mut f) = entry.stat_file.take() { match get_all_data_from_file(&mut f, 1024) { Ok(data) => { @@ -500,7 +497,7 @@ pub(crate) fn _get_process_data( let mut p = retrieve_all_new_process_info(pid, proc_list, &parts, path, info, refresh_kind, uptime); - p.stat_file = stat_file; + p.inner.stat_file = stat_file; return Ok((Some(p), pid)); }; @@ -519,7 +516,7 @@ pub(crate) fn _get_process_data( #[allow(clippy::too_many_arguments)] fn update_time_and_memory( path: &Path, - entry: &mut Process, + entry: &mut ProcessInner, parts: &[&str], parent_memory: u64, parent_virtual_memory: u64, @@ -559,7 +556,7 @@ fn update_time_and_memory( } pub(crate) fn refresh_procs( - proc_list: &mut Process, + proc_list: &mut ProcessInner, path: &Path, pid: Pid, uptime: u64, diff --git a/src/unix/linux/system.rs b/src/unix/linux/system.rs index 879460830..c39ddc970 100644 --- a/src/unix/linux/system.rs +++ b/src/unix/linux/system.rs @@ -1,9 +1,9 @@ // Take a look at the license at the top of the repository in the LICENSE file. use crate::sys::cpu::*; -use crate::sys::process::*; +use crate::sys::process::{_get_process_data, compute_cpu_usage, refresh_procs, unset_updated}; use crate::sys::utils::{get_all_data, to_u64}; -use crate::{CpuRefreshKind, LoadAvg, Pid, ProcessRefreshKind}; +use crate::{CpuRefreshKind, LoadAvg, Pid, Process, ProcessInner, ProcessRefreshKind}; use libc::{self, c_char, sysconf, _SC_CLK_TCK, _SC_HOST_NAME_MAX, _SC_PAGESIZE}; use std::cmp::min; @@ -153,7 +153,8 @@ impl SystemInner { (0., false, 0.) }; - self.process_list.tasks.retain(|_, proc_| { + self.process_list.inner.tasks.retain(|_, proc_| { + let proc_ = &mut proc_.inner; if !proc_.updated { return false; } @@ -173,7 +174,9 @@ impl SystemInner { impl SystemInner { pub(crate) fn new() -> Self { Self { - process_list: Process::new(Pid(0)), + process_list: Process { + inner: ProcessInner::new(Pid(0)), + }, mem_total: 0, mem_free: 0, mem_available: 0, @@ -263,7 +266,7 @@ impl SystemInner { pub(crate) fn refresh_processes_specifics(&mut self, refresh_kind: ProcessRefreshKind) { let uptime = self.uptime(); refresh_procs( - &mut self.process_list, + &mut self.process_list.inner, Path::new("/proc"), Pid(0), uptime, @@ -282,14 +285,14 @@ impl SystemInner { let uptime = self.uptime(); match _get_process_data( &Path::new("/proc/").join(pid.to_string()), - &mut self.process_list, + &mut self.process_list.inner, Pid(0), uptime, &self.info, refresh_kind, ) { Ok((Some(p), pid)) => { - self.process_list.tasks.insert(pid, p); + self.process_list.inner.tasks.insert(pid, p); } Ok(_) => {} Err(_e) => { @@ -309,12 +312,13 @@ impl SystemInner { let total_time = total_time / self.cpus.len() as f32; let max_cpu_usage = self.get_max_process_cpu_usage(); - if let Some(p) = self.process_list.tasks.get_mut(&pid) { + if let Some(p) = self.process_list.inner.tasks.get_mut(&pid) { + let p = &mut p.inner; compute_cpu_usage(p, total_time, max_cpu_usage); unset_updated(p); } - } else if let Some(p) = self.process_list.tasks.get_mut(&pid) { - unset_updated(p); + } else if let Some(p) = self.process_list.inner.tasks.get_mut(&pid) { + unset_updated(&mut p.inner); } true } @@ -324,11 +328,11 @@ impl SystemInner { // Need to be moved into a "common" file to avoid duplication. pub(crate) fn processes(&self) -> &HashMap { - &self.process_list.tasks + &self.process_list.inner.tasks } pub(crate) fn process(&self, pid: Pid) -> Option<&Process> { - self.process_list.tasks.get(&pid) + self.process_list.inner.tasks.get(&pid) } pub(crate) fn global_cpu_info(&self) -> &Cpu { diff --git a/src/unknown/mod.rs b/src/unknown/mod.rs index f607033c8..53bb589f7 100644 --- a/src/unknown/mod.rs +++ b/src/unknown/mod.rs @@ -12,7 +12,7 @@ pub use self::component::{Component, Components}; pub use self::cpu::Cpu; pub(crate) use self::disk::{DiskInner, DisksInner}; pub use self::network::NetworkData; -pub use self::process::Process; +pub(crate) use self::process::ProcessInner; pub(crate) use self::system::SystemInner; pub(crate) use self::users::get_users; pub use self::users::User; diff --git a/src/unknown/process.rs b/src/unknown/process.rs index 4e116d7df..0d6fe2266 100644 --- a/src/unknown/process.rs +++ b/src/unknown/process.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use crate::{DiskUsage, Gid, Pid, ProcessExt, ProcessStatus, Signal, Uid}; +use crate::{DiskUsage, Gid, Pid, ProcessStatus, Signal, Uid}; use std::fmt; use std::path::Path; @@ -11,96 +11,95 @@ impl fmt::Display for ProcessStatus { } } -#[doc = include_str!("../../md_doc/process.md")] -pub struct Process { +pub(crate) struct ProcessInner { pid: Pid, parent: Option, } -impl ProcessExt for Process { - fn kill_with(&self, _signal: Signal) -> Option { +impl ProcessInner { + pub(crate) fn kill_with(&self, _signal: Signal) -> Option { None } - fn name(&self) -> &str { + pub(crate) fn name(&self) -> &str { "" } - fn cmd(&self) -> &[String] { + pub(crate) fn cmd(&self) -> &[String] { &[] } - fn exe(&self) -> &Path { + pub(crate) fn exe(&self) -> &Path { Path::new("") } - fn pid(&self) -> Pid { + pub(crate) fn pid(&self) -> Pid { self.pid } - fn environ(&self) -> &[String] { + pub(crate) fn environ(&self) -> &[String] { &[] } - fn cwd(&self) -> &Path { + pub(crate) fn cwd(&self) -> &Path { Path::new("") } - fn root(&self) -> &Path { + pub(crate) fn root(&self) -> &Path { Path::new("") } - fn memory(&self) -> u64 { + pub(crate) fn memory(&self) -> u64 { 0 } - fn virtual_memory(&self) -> u64 { + pub(crate) fn virtual_memory(&self) -> u64 { 0 } - fn parent(&self) -> Option { + pub(crate) fn parent(&self) -> Option { self.parent } - fn status(&self) -> ProcessStatus { + pub(crate) fn status(&self) -> ProcessStatus { ProcessStatus::Unknown(0) } - fn start_time(&self) -> u64 { + pub(crate) fn start_time(&self) -> u64 { 0 } - fn run_time(&self) -> u64 { + pub(crate) fn run_time(&self) -> u64 { 0 } - fn cpu_usage(&self) -> f32 { + pub(crate) fn cpu_usage(&self) -> f32 { 0.0 } - fn disk_usage(&self) -> DiskUsage { + pub(crate) fn disk_usage(&self) -> DiskUsage { DiskUsage::default() } - fn user_id(&self) -> Option<&Uid> { + pub(crate) fn user_id(&self) -> Option<&Uid> { None } - fn effective_user_id(&self) -> Option<&Uid> { + pub(crate) fn effective_user_id(&self) -> Option<&Uid> { None } - fn group_id(&self) -> Option { + pub(crate) fn group_id(&self) -> Option { None } - fn effective_group_id(&self) -> Option { + pub(crate) fn effective_group_id(&self) -> Option { None } - fn wait(&self) {} + pub(crate) fn wait(&self) {} - fn session_id(&self) -> Option { + pub(crate) fn session_id(&self) -> Option { None } } diff --git a/src/unknown/system.rs b/src/unknown/system.rs index 06c19838a..7b772c2d1 100644 --- a/src/unknown/system.rs +++ b/src/unknown/system.rs @@ -1,9 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use crate::{ - sys::{Cpu, Process}, - CpuRefreshKind, LoadAvg, Pid, ProcessRefreshKind, -}; +use crate::{sys::Cpu, CpuRefreshKind, LoadAvg, Pid, Process, ProcessRefreshKind}; use std::collections::HashMap; diff --git a/src/windows/mod.rs b/src/windows/mod.rs index 8927b96c5..c525e5762 100644 --- a/src/windows/mod.rs +++ b/src/windows/mod.rs @@ -16,7 +16,7 @@ pub use self::component::{Component, Components}; pub use self::cpu::Cpu; pub(crate) use self::disk::{DiskInner, DisksInner}; pub use self::network::NetworkData; -pub use self::process::Process; +pub(crate) use self::process::ProcessInner; pub use self::sid::Sid; pub(crate) use self::system::SystemInner; pub(crate) use self::users::get_users; diff --git a/src/windows/process.rs b/src/windows/process.rs index e2cdaa2d9..d3e3299eb 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -2,9 +2,7 @@ use crate::sys::system::is_proc_running; use crate::windows::Sid; -use crate::{ - DiskUsage, Gid, Pid, PidExt, ProcessExt, ProcessRefreshKind, ProcessStatus, Signal, Uid, -}; +use crate::{DiskUsage, Gid, Pid, PidExt, ProcessRefreshKind, ProcessStatus, Signal, Uid}; use std::ffi::OsString; use std::fmt; @@ -185,8 +183,7 @@ impl Drop for HandleWrapper { unsafe impl Send for HandleWrapper {} unsafe impl Sync for HandleWrapper {} -#[doc = include_str!("../../md_doc/process.md")] -pub struct Process { +pub(crate) struct ProcessInner { name: String, cmd: Vec, exe: PathBuf, @@ -337,12 +334,12 @@ unsafe fn get_exe(process_handler: &HandleWrapper) -> PathBuf { PathBuf::from(null_terminated_wchar_to_string(&exe_buf)) } -impl Process { +impl ProcessInner { pub(crate) fn new_from_pid( pid: Pid, now: u64, refresh_kind: ProcessRefreshKind, - ) -> Option { + ) -> Option { unsafe { let process_handler = get_process_handler(pid)?; let mut info: MaybeUninit = MaybeUninit::uninit(); @@ -377,7 +374,7 @@ impl Process { None }; let user_id = get_process_user_id(&process_handler, refresh_kind); - Some(Process { + Some(Self { handle: Some(Arc::new(process_handler)), name, pid, @@ -412,7 +409,7 @@ impl Process { name: String, now: u64, refresh_kind: ProcessRefreshKind, - ) -> Process { + ) -> Self { if let Some(handle) = get_process_handler(pid) { unsafe { let exe = get_exe(&handle); @@ -427,7 +424,7 @@ impl Process { }; let (start_time, run_time) = get_start_and_run_time(*handle, now); let user_id = get_process_user_id(&handle, refresh_kind); - Process { + Self { handle: Some(Arc::new(handle)), name, pid, @@ -453,7 +450,7 @@ impl Process { } } } else { - Process { + Self { handle: None, name, pid, @@ -503,10 +500,8 @@ impl Process { pub(crate) fn get_start_time(&self) -> Option { self.handle.as_ref().map(|handle| get_start_time(***handle)) } -} -impl ProcessExt for Process { - fn kill_with(&self, signal: Signal) -> Option { + pub(crate) fn kill_with(&self, signal: Signal) -> Option { crate::sys::convert_signal(signal)?; let mut kill = process::Command::new("taskkill.exe"); kill.arg("/PID").arg(self.pid.to_string()).arg("/F"); @@ -517,63 +512,63 @@ impl ProcessExt for Process { } } - fn name(&self) -> &str { + pub(crate) fn name(&self) -> &str { &self.name } - fn cmd(&self) -> &[String] { + pub(crate) fn cmd(&self) -> &[String] { &self.cmd } - fn exe(&self) -> &Path { + pub(crate) fn exe(&self) -> &Path { self.exe.as_path() } - fn pid(&self) -> Pid { + pub(crate) fn pid(&self) -> Pid { self.pid } - fn environ(&self) -> &[String] { + pub(crate) fn environ(&self) -> &[String] { &self.environ } - fn cwd(&self) -> &Path { + pub(crate) fn cwd(&self) -> &Path { self.cwd.as_path() } - fn root(&self) -> &Path { + pub(crate) fn root(&self) -> &Path { self.root.as_path() } - fn memory(&self) -> u64 { + pub(crate) fn memory(&self) -> u64 { self.memory } - fn virtual_memory(&self) -> u64 { + pub(crate) fn virtual_memory(&self) -> u64 { self.virtual_memory } - fn parent(&self) -> Option { + pub(crate) fn parent(&self) -> Option { self.parent } - fn status(&self) -> ProcessStatus { + pub(crate) fn status(&self) -> ProcessStatus { self.status } - fn start_time(&self) -> u64 { + pub(crate) fn start_time(&self) -> u64 { self.start_time } - fn run_time(&self) -> u64 { + pub(crate) fn run_time(&self) -> u64 { self.run_time } - fn cpu_usage(&self) -> f32 { + pub(crate) fn cpu_usage(&self) -> f32 { self.cpu_usage } - fn disk_usage(&self) -> DiskUsage { + pub(crate) fn disk_usage(&self) -> DiskUsage { DiskUsage { written_bytes: self.written_bytes.saturating_sub(self.old_written_bytes), total_written_bytes: self.written_bytes, @@ -582,23 +577,23 @@ impl ProcessExt for Process { } } - fn user_id(&self) -> Option<&Uid> { + pub(crate) fn user_id(&self) -> Option<&Uid> { self.user_id.as_ref() } - fn effective_user_id(&self) -> Option<&Uid> { + pub(crate) fn effective_user_id(&self) -> Option<&Uid> { None } - fn group_id(&self) -> Option { + pub(crate) fn group_id(&self) -> Option { None } - fn effective_group_id(&self) -> Option { + pub(crate) fn effective_group_id(&self) -> Option { None } - fn wait(&self) { + pub(crate) fn wait(&self) { if let Some(handle) = self.get_handle() { while is_proc_running(handle) { if get_start_time(handle) != self.start_time() { @@ -613,7 +608,7 @@ impl ProcessExt for Process { } } - fn session_id(&self) -> Option { + pub(crate) fn session_id(&self) -> Option { unsafe { let mut out = 0; if ProcessIdToSessionId(self.pid.as_u32(), &mut out).is_ok() { @@ -1031,7 +1026,7 @@ fn check_sub(a: u64, b: u64) -> u64 { /// Before changing this function, you must consider the following: /// -pub(crate) fn compute_cpu_usage(p: &mut Process, nb_cpus: u64) { +pub(crate) fn compute_cpu_usage(p: &mut ProcessInner, nb_cpus: u64) { unsafe { let mut ftime: FILETIME = zeroed(); let mut fsys: FILETIME = zeroed(); @@ -1081,7 +1076,7 @@ pub(crate) fn compute_cpu_usage(p: &mut Process, nb_cpus: u64) { } } -pub(crate) fn update_disk_usage(p: &mut Process) { +pub(crate) fn update_disk_usage(p: &mut ProcessInner) { let mut counters = MaybeUninit::::uninit(); if let Some(handle) = p.get_handle() { @@ -1099,7 +1094,7 @@ pub(crate) fn update_disk_usage(p: &mut Process) { } } -pub(crate) fn update_memory(p: &mut Process) { +pub(crate) fn update_memory(p: &mut ProcessInner) { if let Some(handle) = p.get_handle() { unsafe { let mut pmc: PROCESS_MEMORY_COUNTERS_EX = zeroed(); diff --git a/src/windows/system.rs b/src/windows/system.rs index 3bd2c35cf..d228f756f 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -1,11 +1,12 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use crate::{CpuRefreshKind, LoadAvg, Pid, ProcessExt, ProcessRefreshKind}; +use crate::{CpuRefreshKind, LoadAvg, Pid, ProcessRefreshKind}; use crate::sys::cpu::*; -use crate::sys::process::{get_start_time, update_memory, Process}; +use crate::sys::process::{get_start_time, update_memory}; use crate::sys::tools::*; use crate::sys::utils::{get_now, get_reg_string_value, get_reg_value_u32}; +use crate::{Process, ProcessInner}; use crate::utils::into_iter; @@ -178,10 +179,10 @@ impl SystemInner { } // We need to re-make the process because the PID owner changed. } - if let Some(mut p) = Process::new_from_pid(pid, now, refresh_kind) { + if let Some(mut p) = ProcessInner::new_from_pid(pid, now, refresh_kind) { p.update(refresh_kind, nb_cpus, now); p.updated = false; - self.process_list.insert(pid, p); + self.process_list.insert(pid, Process { inner: p }); true } else { false @@ -283,6 +284,7 @@ impl SystemInner { let pi = unsafe { ptr::read_unaligned(pi.0) }; let pid = Pid(pi.UniqueProcessId as _); if let Some(proc_) = unsafe { (*process_list.0.get()).get_mut(&pid) } { + let proc_ = &mut proc_.inner; if proc_ .get_start_time() .map(|start| start == proc_.start_time()) @@ -297,7 +299,7 @@ impl SystemInner { sysinfo_debug!("owner changed for PID {}", proc_.pid()); } let name = get_process_name(&pi, pid); - let mut p = Process::new_full( + let mut p = ProcessInner::new_full( pid, if pi.InheritedFromUniqueProcessId as usize != 0 { Some(Pid(pi.InheritedFromUniqueProcessId as _)) @@ -311,15 +313,15 @@ impl SystemInner { refresh_kind, ); p.update(refresh_kind, nb_cpus, now); - Some(p) + Some(Process { inner: p }) }) .collect::>(); for p in processes.into_iter() { self.process_list.insert(p.pid(), p); } self.process_list.retain(|_, v| { - let x = v.updated; - v.updated = false; + let x = v.inner.updated; + v.inner.updated = false; x }); } @@ -458,6 +460,7 @@ fn refresh_existing_process( now: u64, refresh_kind: ProcessRefreshKind, ) -> Option { + let proc_ = &mut proc_.inner; if let Some(handle) = proc_.get_handle() { if get_start_time(handle) != proc_.start_time() { sysinfo_debug!("owner changed for PID {}", proc_.pid()); diff --git a/tests/code_checkers/signals.rs b/tests/code_checkers/signals.rs index e97b402ca..3709d1160 100644 --- a/tests/code_checkers/signals.rs +++ b/tests/code_checkers/signals.rs @@ -26,7 +26,7 @@ fn check_kill_decl<'a>(lines: &mut impl Iterator, p: &Path) -> u while let Some(line) = lines.next() { let trimmed = line.trim(); if trimmed.starts_with("fn kill(") { - show_error(p, "`ProcessExt::kill` should not be reimplemented!"); + show_error(p, "`Process::kill` should not be reimplemented!"); errors += 1; } else if trimmed.starts_with("fn kill_with(") { if let Some(line) = lines.next() { @@ -34,7 +34,7 @@ fn check_kill_decl<'a>(lines: &mut impl Iterator, p: &Path) -> u if trimmed.ends_with("crate::sys::convert_signal(signal)?;") || trimmed == "None" { continue; } else { - show_error(p, "`ProcessExt::kill_with` should use `convert_signal`"); + show_error(p, "`Process::kill_with` should use `convert_signal`"); errors += 1; } } @@ -52,10 +52,10 @@ pub fn check_signals(content: &str, p: &Path) -> TestResult { while let Some(line) = lines.next() { let trimmed = line.trim(); - if trimmed.starts_with("impl SystemExt for System {") { + if trimmed.starts_with("impl SystemInner {") { res.nb_tests += 1; res.nb_errors += check_supported_signals_decl(&mut lines, p); - } else if trimmed.starts_with("impl ProcessExt for Process {") { + } else if trimmed.starts_with("impl ProcessInner {") { res.nb_tests += 1; res.nb_errors += check_kill_decl(&mut lines, p); } diff --git a/tests/process.rs b/tests/process.rs index 2e0cd6006..4c8bc23e2 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use sysinfo::{Pid, PidExt, ProcessExt}; +use sysinfo::{Pid, PidExt}; #[test] fn test_process() { @@ -211,7 +211,7 @@ fn test_process_disk_usage() { use std::fs; use std::fs::File; use std::io::prelude::*; - use sysinfo::{get_current_pid, ProcessExt}; + use sysinfo::get_current_pid; if !sysinfo::IS_SUPPORTED || cfg!(feature = "apple-sandbox") { return; @@ -426,7 +426,7 @@ fn test_refresh_tasks() { assert!(s .process(pid) .unwrap() - .tasks + .tasks() .values() .any(|t| t.name() == task_name)); @@ -438,7 +438,7 @@ fn test_refresh_tasks() { assert!(!s .process(pid) .unwrap() - .tasks + .tasks() .values() .any(|t| t.name() == task_name)); } @@ -599,7 +599,7 @@ fn test_process_iterator_lifetimes() { // Regression test for . #[test] fn test_process_cpu_usage() { - use sysinfo::{ProcessExt, System}; + use sysinfo::System; if !sysinfo::IS_SUPPORTED || cfg!(feature = "apple-sandbox") { return; @@ -618,7 +618,7 @@ fn test_process_cpu_usage() { #[test] fn test_process_creds() { - use sysinfo::{ProcessExt, System}; + use sysinfo::System; if !sysinfo::IS_SUPPORTED || cfg!(feature = "apple-sandbox") { return;