Skip to content

Commit

Permalink
Merge pull request #1140 from GuillaumeGomez/improve-process-refresh-…
Browse files Browse the repository at this point in the history
…kind-related

Update `Process::refresh_process` and `Process::refresh_processes` default `ProcessRefreshKind` used
  • Loading branch information
GuillaumeGomez authored Nov 14, 2023
2 parents fa1275a + 9fa2195 commit fb1594c
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 27 deletions.
96 changes: 76 additions & 20 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,19 +234,37 @@ impl System {

/// Gets all processes and updates their information.
///
/// It does the same as `system.refresh_processes_specifics(ProcessRefreshKind::everything())`.
/// It does the same as:
///
/// ```no_run
/// # use sysinfo::{ProcessRefreshKind, System};
/// # let mut system = System::new();
/// system.refresh_processes_specifics(
/// ProcessRefreshKind::new()
/// .with_memory()
/// .with_cpu()
/// .with_disk_usage(),
/// );
/// ```
///
/// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
/// by using [`set_open_files_limit`][crate::set_open_files_limit].
///
/// Example:
///
/// ```no_run
/// use sysinfo::System;
///
/// let mut s = System::new_all();
/// s.refresh_processes();
/// ```
pub fn refresh_processes(&mut self) {
self.refresh_processes_specifics(ProcessRefreshKind::everything());
self.refresh_processes_specifics(
ProcessRefreshKind::new()
.with_memory()
.with_cpu()
.with_disk_usage(),
);
}

/// Gets all processes and updates the specified information.
Expand All @@ -268,8 +286,25 @@ impl System {
/// exist (it will **NOT** be removed from the processes if it doesn't exist anymore). If it
/// isn't listed yet, it'll be added.
///
/// It is the same as calling
/// `sys.refresh_process_specifics(pid, ProcessRefreshKind::everything())`.
/// It is the same as calling:
///
/// ```no_run
/// # use sysinfo::{Pid, ProcessRefreshKind, System};
/// # let mut system = System::new();
/// # let pid = Pid::from(0);
/// system.refresh_process_specifics(
/// pid,
/// ProcessRefreshKind::new()
/// .with_memory()
/// .with_cpu()
/// .with_disk_usage(),
/// );
/// ```
///
/// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
/// by using [`set_open_files_limit`][crate::set_open_files_limit].
///
/// Example:
///
/// ```no_run
/// use sysinfo::{Pid, System};
Expand All @@ -278,13 +313,22 @@ impl System {
/// s.refresh_process(Pid::from(1337));
/// ```
pub fn refresh_process(&mut self, pid: Pid) -> bool {
self.refresh_process_specifics(pid, ProcessRefreshKind::everything())
self.refresh_process_specifics(
pid,
ProcessRefreshKind::new()
.with_memory()
.with_cpu()
.with_disk_usage(),
)
}

/// Refreshes *only* the process corresponding to `pid`. Returns `false` if the process doesn't
/// exist (it will **NOT** be removed from the processes if it doesn't exist anymore). If it
/// isn't listed yet, it'll be added.
///
/// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
/// by using [`set_open_files_limit`][crate::set_open_files_limit].
///
/// ```no_run
/// use sysinfo::{Pid, ProcessRefreshKind, System};
///
Expand Down Expand Up @@ -346,16 +390,13 @@ impl System {
/// println!("{} {}", process.pid(), process.name());
/// }
/// ```
// FIXME: replace the returned type with `impl Iterator<Item = &Process>` when it's supported!
pub fn processes_by_name<'a: 'b, 'b>(
&'a self,
name: &'b str,
) -> Box<dyn Iterator<Item = &'a Process> + 'b> {
Box::new(
self.processes()
.values()
.filter(move |val: &&Process| val.name().contains(name)),
)
) -> impl Iterator<Item = &'a Process> + 'b {
self.processes()
.values()
.filter(move |val: &&Process| val.name().contains(name))
}

/// Returns an iterator of processes with exactly the given `name`.
Expand All @@ -377,16 +418,13 @@ impl System {
/// println!("{} {}", process.pid(), process.name());
/// }
/// ```
// FIXME: replace the returned type with `impl Iterator<Item = &Process>` when it's supported!
pub fn processes_by_exact_name<'a: 'b, 'b>(
&'a self,
name: &'b str,
) -> Box<dyn Iterator<Item = &'a Process> + 'b> {
Box::new(
self.processes()
.values()
.filter(move |val: &&Process| val.name() == name),
)
) -> impl Iterator<Item = &'a Process> + 'b {
self.processes()
.values()
.filter(move |val: &&Process| val.name() == name)
}

/// Returns "global" CPUs information (aka the addition of all the CPUs).
Expand Down Expand Up @@ -1377,6 +1415,12 @@ assert_eq!(r.", stringify!($name), "().is_some(), false);

/// Used to determine what you want to refresh specifically on the [`Process`] type.
///
/// When all refresh are ruled out, a [`Process`] will still retrieve the following information:
/// * Process ID ([`Pid`])
/// * Parent process ID
/// * Process name
/// * Start time
///
/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
/// the information won't be retrieved if the information is accessible without needing
/// extra computation.
Expand Down Expand Up @@ -1455,7 +1499,19 @@ impl ProcessRefreshKind {
with_disk_usage,
without_disk_usage
);
impl_get_set!(ProcessRefreshKind, user, with_user, without_user);
impl_get_set!(
ProcessRefreshKind,
user,
with_user,
without_user,
"\
It will retrieve the following information:
* user ID
* user effective ID (if available on the platform)
* user group ID (if available on the platform)
* user effective ID (if available on the platform)"
);
impl_get_set!(ProcessRefreshKind, memory, with_memory, without_memory);
impl_get_set!(ProcessRefreshKind, cwd, with_cwd, without_cwd);
impl_get_set!(ProcessRefreshKind, root, with_root, without_root);
Expand Down
2 changes: 1 addition & 1 deletion src/unix/linux/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ fn update_proc_info(
refresh_user_group_ids(p, proc_path);
}

if refresh_kind.exe() && p.exe == Path::new("") {
if refresh_kind.exe() && p.exe.as_os_str().is_empty() {
match proc_path.join("exe").read_link() {
Ok(exe_path) => p.exe = exe_path,
Err(_error) => {
Expand Down
31 changes: 25 additions & 6 deletions tests/process.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use sysinfo::{Pid, System};
use sysinfo::{Pid, ProcessRefreshKind, System};

#[test]
fn test_process() {
Expand All @@ -14,7 +14,14 @@ fn test_process() {
assert!(s
.processes()
.values()
.any(|p| !p.exe().to_str().unwrap_or("").is_empty()));
.all(|p| p.exe().as_os_str().is_empty()));

let mut s = System::new();
s.refresh_processes_specifics(ProcessRefreshKind::new().with_exe());
assert!(s
.processes()
.values()
.any(|p| !p.exe().as_os_str().is_empty()));
}

#[test]
Expand All @@ -41,7 +48,7 @@ fn test_cwd() {
let pid = Pid::from_u32(p.id() as _);
std::thread::sleep(std::time::Duration::from_secs(1));
let mut s = System::new();
s.refresh_processes();
s.refresh_processes_specifics(ProcessRefreshKind::new().with_cwd());
p.kill().expect("Unable to kill process.");

let processes = s.processes();
Expand Down Expand Up @@ -78,7 +85,7 @@ fn test_cmd() {
std::thread::sleep(std::time::Duration::from_millis(500));
let mut s = System::new();
assert!(s.processes().is_empty());
s.refresh_processes();
s.refresh_processes_specifics(ProcessRefreshKind::new().with_cmd());
p.kill().expect("Unable to kill process.");
assert!(!s.processes().is_empty());
if let Some(process) = s.process(Pid::from_u32(p.id() as _)) {
Expand Down Expand Up @@ -153,7 +160,7 @@ fn test_environ() {
let pid = Pid::from_u32(p.id() as _);
let mut s = System::new();

s.refresh_processes();
s.refresh_processes_specifics(ProcessRefreshKind::new().with_environ());

let processes = s.processes();
let proc_ = processes.get(&pid);
Expand All @@ -179,7 +186,19 @@ fn test_process_refresh() {
s.refresh_process(sysinfo::get_current_pid().expect("failed to get current pid"));
assert!(s
.process(sysinfo::get_current_pid().expect("failed to get current pid"))
.is_some(),);
.is_some());

assert!(s
.processes()
.iter()
.all(|(_, p)| p.exe().as_os_str().is_empty()
&& p.environ().is_empty()
&& p.cwd().as_os_str().is_empty()
&& p.cmd().is_empty()));
assert!(s
.processes()
.iter()
.any(|(_, p)| !p.name().is_empty() && p.memory() != 0));
}

#[test]
Expand Down

0 comments on commit fb1594c

Please sign in to comment.