Repository: GuillaumeGomez/sysinfo (Rust)

Issue:
Tasks aren't refreshed in `System`
**Describe the bug**

I'm using `.tasks()` to count the # of processes on *Linux*.

Tasks aren't refreshed in an existing instance of `System`. To get the correct value, I have to create a new instance of `System` every time.

- OS: *Arch Linux*
- `sysinfo` version: v0.33.1

**To Reproduce**

In the following code, what's printed should match, but they don't:

```rust
use std::{collections::HashSet, thread, time::Duration};

use sysinfo::{Pid, ProcessRefreshKind, ProcessesToUpdate, RefreshKind, System };

fn get_tasks(system: &System) -> HashSet<Pid> {
  let pid_to_process = system.processes();
  let mut task_pids: HashSet<Pid> = HashSet::new();
  for process in pid_to_process.values() {
    if let Some(tasks) = process.tasks() {
      task_pids.extend(tasks)
    }
  }
  task_pids
}

pub fn main() {
  let scheduler = thread::spawn(|| {
    let mut system = System::new_with_specifics(RefreshKind::nothing());

    loop {
      system.refresh_processes_specifics(ProcessesToUpdate::All, true, ProcessRefreshKind::nothing());

      let mut system_new = System::new_with_specifics(RefreshKind::nothing());
      system_new.refresh_processes_specifics(ProcessesToUpdate::All, true, ProcessRefreshKind::nothing());

      println!("{} {}", get_tasks(&system).len(), get_tasks(&system_new).len());
      thread::sleep(Duration::from_secs(1));
    }
  });
  scheduler.join().expect("Scheduler panicked");
}
```


Discussion: The above code snippet produces the correct result on Kali WSL. 

Perhaps try using `ProcessRefreshKind::everything()`. Does this produce a different result? If not, can you attach the output you're getting?

Below is the output I'm getting using your code snippet, where both numbers are matching.

## Terminal Output (Kali Linux WSL):
```
19 19
19 19
19 19
19 19
19 19
19 19
19 19
19 19
19 19
19 19
19 19
19 19
19 19
19 19
^C
```
When you say "tasks aren't refreshed", do you mean you get the same count every time or do you mean the existing tasks information are not updated?
The counts will change as programs are opened or closed. The 2 counts should match but they don't.

Using data from `system_new` in my code, I can get a total process count to match that of `top`, but not with `system`. This is what I mean when I say that it seems like "tasks aren't refreshed". The value for `system` is incorrect.
That doesn't help at all trying to understand you. ^^'

So the process list is not refreshed correctly, right?
The list of PIDs are correct, as in this always returns `true`:

```rust
println!("{}", system.processes().keys().copied().collect::<HashSet<Pid>>() == system_new.processes().keys().copied().collect::<HashSet<Pid>>());
```

However `.tasks()` isn't being refreshed correctly, as shown in the first post. This gives different values, with `system_new` giving the correct values and `system` incorrect ones. All I need is this test case to pass. My first post uses `.len()` but this is a more proper test:

```rust
println!("{}", get_tasks(&system) == get_tasks(&system_new));
```

This will print `true` a few times then stay `false`.



Fix (patch):
diff --git a/src/unix/linux/process.rs b/src/unix/linux/process.rs
index 73f2bd97d..a824c60ad 100644
--- a/src/unix/linux/process.rs
+++ b/src/unix/linux/process.rs
@@ -508,7 +508,8 @@ fn update_existing_process(
     uptime: u64,
     info: &SystemInfo,
     refresh_kind: ProcessRefreshKind,
-) -> Result<(Option<Process>, Pid), ()> {
+    tasks: Option<HashSet<Pid>>,
+) -> Result<Option<Process>, ()> {
     let entry = &mut proc.inner;
     let data = if let Some(mut f) = entry.stat_file.take() {
         match get_all_data_from_file(&mut f, 1024) {
@@ -526,6 +527,8 @@ fn update_existing_process(
     } else {
         _get_stat_data(&entry.proc_path, &mut entry.stat_file)?
     };
+    entry.tasks = tasks;
+
     let parts = parse_stat_file(&data).ok_or(())?;
     let start_time_without_boot_time = compute_start_time_without_boot_time(&parts, info);
 
@@ -546,7 +549,7 @@ fn update_existing_process(
         );
 
         refresh_user_group_ids(entry, &mut proc_path, refresh_kind);
-        return Ok((None, entry.pid));
+        return Ok(None);
     }
     // If we're here, it means that the PID still exists but it's a different process.
     let p = retrieve_all_new_process_info(
@@ -560,9 +563,10 @@ fn update_existing_process(
     );
     *proc = p;
     // Since this PID is already in the HashMap, no need to add it again.
-    Ok((None, proc.inner.pid))
+    Ok(None)
 }
 
+#[allow(clippy::too_many_arguments)]
 pub(crate) fn _get_process_data(
     path: &Path,
     proc_list: &mut HashMap<Pid, Process>,
@@ -571,18 +575,20 @@ pub(crate) fn _get_process_data(
     uptime: u64,
     info: &SystemInfo,
     refresh_kind: ProcessRefreshKind,
-) -> Result<(Option<Process>, Pid), ()> {
+    tasks: Option<HashSet<Pid>>,
+) -> Result<Option<Process>, ()> {
     if let Some(ref mut entry) = proc_list.get_mut(&pid) {
-        return update_existing_process(entry, parent_pid, uptime, info, refresh_kind);
+        return update_existing_process(entry, parent_pid, uptime, info, refresh_kind, tasks);
     }
     let mut stat_file = None;
     let data = _get_stat_data(path, &mut stat_file)?;
     let parts = parse_stat_file(&data).ok_or(())?;
 
-    let mut p =
+    let mut new_process =
         retrieve_all_new_process_info(pid, parent_pid, &parts, path, info, refresh_kind, uptime);
-    p.inner.stat_file = stat_file;
-    Ok((Some(p), pid))
+    new_process.inner.stat_file = stat_file;
+    new_process.inner.tasks = tasks;
+    Ok(Some(new_process))
 }
 
 fn old_get_memory(entry: &mut ProcessInner, str_parts: &[&str], info: &SystemInfo) {
@@ -796,21 +802,20 @@ pub(crate) fn refresh_procs(
             .flatten()
             .filter(|e| filter_callback(e, filter))
             .filter_map(|e| {
-                let (mut p, _) = _get_process_data(
+                let proc_list = proc_list.get();
+                let new_process = _get_process_data(
                     e.path.as_path(),
-                    proc_list.get(),
+                    proc_list,
                     e.pid,
                     e.parent_pid,
                     uptime,
                     info,
                     refresh_kind,
+                    e.tasks,
                 )
                 .ok()?;
                 nb_updated.fetch_add(1, Ordering::Relaxed);
-                if let Some(ref mut p) = p {
-                    p.inner.tasks = e.tasks;
-                }
-                p
+                new_process
             })
             .collect::<Vec<_>>()
     };