A system handler to get information and interact with processes written in Rust

Overview

sysinfo img_github_ci

A system handler to interact with processes.

Supports the following platforms:

  • Linux
  • Raspberry Pi
  • Android
  • macOS
  • iOS
  • Windows

The minimum-supported version of rustc is 1.45.

Use in binaries distributed on the MacOS App Store

Apple has restrictions as to which APIs can be used in binaries distributed through the app store. By default, sysinfo is not compatible with these restrictions. You can use the apple-app-store feature flag to disable the Apple prohibited features.

Running on Raspberry Pi

It'll be difficult to build on Raspberry Pi. A good way-around is to cross-build, then send the executable to your Raspberry Pi.

First install the arm toolchain, for example on Ubuntu: sudo apt-get install gcc-multilib-arm-linux-gnueabihf.

Then configure cargo to use the corresponding toolchain:

cat << EOF > ~/.cargo/config
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
EOF

Finally, cross compile:

rustup target add armv7-unknown-linux-gnueabihf
cargo build --target=armv7-unknown-linux-gnueabihf

Linux on Docker & Windows Subsystem for Linux (WSL)

Virtual Linux systems, such as those run through Docker and Windows Subsystem for Linux (WSL), do not receive host hardware information via /sys/class/hwmon or /sys/class/thermal. As such, querying for components may return no results (or unexpected results) when using this library on virtual systems.

Code example

You have an example into the examples folder. Just run cargo run --example simple to start it. Otherwise, here is a little code sample:

disk list:"); for disk in sys.disks() { println!("{:?}", disk); } // Network data: for (interface_name, data) in sys.networks() { println!("{}: {}/{} B", interface_name, data.received(), data.transmitted()); } // Components temperature: for component in sys.components() { println!("{:?}", component); } // Memory information: println!("total memory: {} KB", sys.total_memory()); println!("used memory : {} KB", sys.used_memory()); println!("total swap : {} KB", sys.total_swap()); println!("used swap : {} KB", sys.used_swap()); // Number of processors println!("NB processors: {}", sys.processors().len()); // To refresh all system information: sys.refresh_all(); // We show the processes and some of their information: for (pid, process) in sys.processes() { println!("[{}] {} {:?}", pid, process.name(), process.disk_usage()); } // Display system information: println!("System name: {:?}", sys.name()); println!("System kernel version: {:?}", sys.kernel_version()); println!("System OS version: {:?}", sys.os_version()); println!("System host name: {:?}", sys.host_name()); ">
use sysinfo::{NetworkExt, NetworksExt, ProcessExt, System, SystemExt};

let mut sys = System::new_all();

// We display the disks:
println!("=> disk list:");
for disk in sys.disks() {
    println!("{:?}", disk);
}

// Network data:
for (interface_name, data) in sys.networks() {
    println!("{}: {}/{} B", interface_name, data.received(), data.transmitted());
}

// Components temperature:
for component in sys.components() {
    println!("{:?}", component);
}

// Memory information:
println!("total memory: {} KB", sys.total_memory());
println!("used memory : {} KB", sys.used_memory());
println!("total swap  : {} KB", sys.total_swap());
println!("used swap   : {} KB", sys.used_swap());

// Number of processors
println!("NB processors: {}", sys.processors().len());

// To refresh all system information:
sys.refresh_all();

// We show the processes and some of their information:
for (pid, process) in sys.processes() {
    println!("[{}] {} {:?}", pid, process.name(), process.disk_usage());
}

// Display system information:
println!("System name:             {:?}", sys.name());
println!("System kernel version:   {:?}", sys.kernel_version());
println!("System OS version:       {:?}", sys.os_version());
println!("System host name:        {:?}", sys.host_name());

By default, sysinfo uses multiple threads. However, this can increase the memory usage on some platforms (macOS for example). The behavior can be disabled by setting default-features = false in Cargo.toml (which disables the multithread cargo feature).

C interface

It's possible to use this crate directly from C. Take a look at the Makefile and at the examples/simple.c file.

To build the C example, just run:

> make
> ./simple
# If needed:
> LD_LIBRARY_PATH=target/release/ ./simple

Benchmarks

You can run the benchmarks locally with rust nightly by doing:

> cargo bench

Here are the current results:

Linux

test bench_new                     ... bench:     182,536 ns/iter (+/- 21,074)
test bench_new_all                 ... bench:  19,911,714 ns/iter (+/- 1,612,109)
test bench_refresh_all             ... bench:   5,649,643 ns/iter (+/- 444,129)
test bench_refresh_components      ... bench:      25,293 ns/iter (+/- 1,748)
test bench_refresh_components_list ... bench:     382,331 ns/iter (+/- 31,620)
test bench_refresh_cpu             ... bench:      13,633 ns/iter (+/- 1,135)
test bench_refresh_disks           ... bench:       2,509 ns/iter (+/- 75)
test bench_refresh_disks_list      ... bench:      51,488 ns/iter (+/- 5,470)
test bench_refresh_memory          ... bench:      12,941 ns/iter (+/- 3,023)
test bench_refresh_networks        ... bench:     256,506 ns/iter (+/- 37,196)
test bench_refresh_networks_list   ... bench:     266,751 ns/iter (+/- 54,535)
test bench_refresh_process         ... bench:     117,372 ns/iter (+/- 8,732)
test bench_refresh_processes       ... bench:   5,125,929 ns/iter (+/- 560,050)
test bench_refresh_system          ... bench:      52,526 ns/iter (+/- 6,786)
test bench_refresh_users_list      ... bench:   2,479,582 ns/iter (+/- 1,063,982)

Windows

test bench_new                     ... bench:   7,119,215 ns/iter (+/- 283,002)
test bench_new_all                 ... bench:  27,364,010 ns/iter (+/- 1,353,879)
test bench_refresh_all             ... bench:   3,125,085 ns/iter (+/- 92,479)
test bench_refresh_components      ... bench:   1,239,478 ns/iter (+/- 45,790)
test bench_refresh_components_list ... bench:   3,197,295 ns/iter (+/- 91,662)
test bench_refresh_cpu             ... bench:      24,973 ns/iter (+/- 1,844)
test bench_refresh_disks           ... bench:      52,321 ns/iter (+/- 1,533)
test bench_refresh_disks_list      ... bench:     114,756 ns/iter (+/- 3,900)
test bench_refresh_memory          ... bench:         581 ns/iter (+/- 25)
test bench_refresh_networks        ... bench:      35,231 ns/iter (+/- 2,210)
test bench_refresh_networks_list   ... bench:     661,170 ns/iter (+/- 56,636)
test bench_refresh_process         ... bench:       1,531 ns/iter (+/- 154)
test bench_refresh_processes       ... bench:   1,070,742 ns/iter (+/- 57,539)
test bench_refresh_system          ... bench:   1,303,291 ns/iter (+/- 44,538)
test bench_refresh_users_list      ... bench:   2,340,562 ns/iter (+/- 83,992)

macOS

test bench_new                     ... bench:      87,569 ns/iter (+/- 11,078)
test bench_new_all                 ... bench:  21,445,081 ns/iter (+/- 523,973)
test bench_refresh_all             ... bench:   1,915,573 ns/iter (+/- 296,132)
test bench_refresh_components      ... bench:     293,904 ns/iter (+/- 63,492)
test bench_refresh_components_list ... bench:     894,462 ns/iter (+/- 161,599)
test bench_refresh_cpu             ... bench:       8,636 ns/iter (+/- 1,244)
test bench_refresh_disks           ... bench:         937 ns/iter (+/- 97)
test bench_refresh_disks_list      ... bench:      25,116 ns/iter (+/- 990)
test bench_refresh_memory          ... bench:       2,172 ns/iter (+/- 67)
test bench_refresh_networks        ... bench:     183,552 ns/iter (+/- 2,253)
test bench_refresh_networks_list   ... bench:     183,623 ns/iter (+/- 11,183)
test bench_refresh_process         ... bench:       5,571 ns/iter (+/- 443)
test bench_refresh_processes       ... bench:     764,125 ns/iter (+/- 28,568)
test bench_refresh_system          ... bench:     333,610 ns/iter (+/- 53,204)
test bench_refresh_users_list      ... bench:  16,816,081 ns/iter (+/- 1,039,374)

Donations

If you appreciate my work and want to support me, you can do it here:

Become a patron

Comments
  • Add FreeBSD support?

    Add FreeBSD support?

    As FreeBSD is still used on lots of places it might be nice to support it.
    I don't think you want to add this but are you open to PRs to support FreeBSD?

    opened by mjarkk 37
  • Add temperature support for M1 Macs

    Add temperature support for M1 Macs

    Would it be possible to add temperature support for M1 Macs?

    On an Intel Mac, I can use the following to find information about the temperature of system components:

    use sysinfo::{System, SystemExt};
    
    fn main() {
        let sys = System::new_all();
    
        for component in sys.get_components() {
            println!("{:?}", component);
        }
    }
    
    PECI CPU: 46.859375°C (max: 0°C)
    CPU Proximity: 42.375°C (max: 0°C)
    Battery: 30.09375°C (max: 0°C)
    

    On M1 Macs, sys.get_components() appears empty.

    $ rustc --version
    rustc 1.51.0 (2fd73fabe 2021-03-23)
    
    $ tail -2 Cargo.toml
    [dependencies]
    sysinfo = "0.16.5"
    
    help wanted mac mac m1 
    opened by mikemadden42 29
  • linux process cpu_usage seems too low

    linux process cpu_usage seems too low

    Hello,

    I am trying to get process.cpu_usage() on linux (ubuntu 18.04). I'd say that it shows low numbers - compared to htop or top.

    For example, when I run stress --cpu 1, I would expect that one of the processes would have cpu usage almost 100.

    htop image

    sysinfo process_cpu_usage{exe="/usr/bin/stress",name="stress",pid="6900",uid="1000"} 0.0033065900206565857

    Usage: https://github.com/mrceperka/process-exporter/blob/dd0f6f2f14d687ec1f530f517bd5f99975dd4ab6/src/main.rs#L119

    Any ideas what am I doing wrong?

    opened by mrceperka 28
  • Malfunctioning in cpu_usage of ProcessExt

    Malfunctioning in cpu_usage of ProcessExt

    The documentation of the method cpu_usage of the process_ext trait says that it returns "Returns the total CPU usage (in %).". However, i wrote a small program that uses this method and it doesn't allways return a number between 0 and 100. I don't think this is a mistake in the code but it would be nice to explain better how it is measured, or at least, what the returned number means. I'm working on windows

    opened by SebastianFelgueras 27
  • Reported command inconsistency between mac os and Linux

    Reported command inconsistency between mac os and Linux

    On mac os, the reported command includes command line arguments. On Linux, this isn't the case. I assumed mac os would behave like Linux and implemented an "args" field for struct Process, which contains the arguments to the process - but on mac os, these are already available via the command field.

    Do you want to keep this inconsistency, should I add an args field for both mac os and linux, should linux adapt to mac os or the other way around? Many options forward.

    opened by shahn 24
  • Add support for getting process current working directory and environment variables on Windows

    Add support for getting process current working directory and environment variables on Windows

    This adds support for getting process current working directory on Windows.

    This will only work on Win64. 32 bit process require quite a bit more work.

    Note that there is a bit of code duplication between this and the code to get command line. I think this could be unified, but I think it would be better to do that in a separate PR. A lot of the same code can be reused to get the process environment variables.

    Thanks!

    opened by ceronman 17
  • get_disks() doesn't return all mounted disks on Mac OS

    get_disks() doesn't return all mounted disks on Mac OS

    I've just started learning Rust. I'm on a 2013 MacBook Air running macOS Sierra and rustc 1.48.0

    I modified the sysinfo example to just print out the disks in the system. My boot disk is an external USB 3.0 SSD. (The internal SSD has been missing since I got the laptop.) Running the code with just the boot disk reports just the boot disk. Attaching my USB 3.0 HD with several partitions including Mac, FAT, and NTFS; still only the boot disk is listed. I added more refresh_* calls but it made no difference. Code:

    use sysinfo::SystemExt;
    
    fn main() {
        let mut system = sysinfo::System::new_all();
    
        // First we update all information of our system struct.
        system.refresh_all();
    
        // And then all disks' information:
        for disk in system.get_disks() {
            println!("{:?}", disk);
        }
    }
    

    Output:

    > Executing task: cargo run --package disklist --bin disklist <
    
       Compiling disklist v0.1.0 (/Users/hippietrail/disklist)
        Finished dev [unoptimized + debuginfo] target(s) in 2.32s
         Running `target/debug/disklist`
    

    UPDATE

    It turns out I had my .toml set up to use version "0.3" of sysinfo, which I must've got from Googling. I changed it to "0.15" to get the latest version. Instead of fixing the problem it now prints out nothing at all. Not even my boot disk is listed.

    UPDATE 2

    It looks like I had code that was still using System::new() from the 0.3 example so I changed it to System::new_all() to match the 0.15 version. Now on my Mac the boot disk shows up again but neither of two different USB hard drives, nor any of their partitions.

    On my Windows 10 machine there's a different problem. The internal SSDs show up and the external USB HDs that don't show up on the Mac do show up, but my SDHC card does not show up.

    opened by hippietrail 17
  • sysinfo System::new opens too many files

    sysinfo System::new opens too many files

    Giving this snippet:

    use sysinfo::{get_current_pid, Pid, ProcessExt, System, SystemExt};
    
    pub fn show_lsof(prefix: &str) {
        let id = std::process::id();
        let out = std::process::Command::new("bash")
            .arg("-c")
            .arg(format!("lsof -p {} | wc -l", id))
            .output()
            .expect("failed to execute process");
        println!("{} {:?}", prefix, out);
    }
    
    fn main() {
        show_lsof("before system::new");
        let mut sys = System::new();
        show_lsof("after system::new");
        println!("Hello, world!");
    }
    

    Run it:

    ulimit -n unlimited
    cargo run
    

    it's showing:

    before system::new Output { status: ExitStatus(ExitStatus(0)), stdout: "84\n", stderr: "" }
    after system::new Output { status: ExitStatus(ExitStatus(0)), stdout: "2318\n", stderr: "" }
    Hello, world!
    
    Checking output of lsof manually, it seems to open 2000+ files of /proc/*/task/*/stat. In our use case we have to keep a reference of sysinfo::System, to log mem and cpu usage every ten seconds; but it opens many files, lead to rust panic: too many open files (if do not increase system default ulimit)
    opened by ailisp 17
  • `sysinfo::System::new()` slow?

    `sysinfo::System::new()` slow?

    A simple program creating a sysinfo::System takes several times longer to run (after cargo build --release) than existing unix utilities from the procps suite (~40ms instead of ~14ms):

    extern crate sysinfo;
    use sysinfo::SystemExt;
    
    fn main()
    {
    	let mut system = sysinfo::System::new();
    }
    

    I haven't done experiments (just observations), so the following analysis is expectation, not known truth:

    I wouldn't expect any significant computation to be going on here, and running strace shows this simple program making many more system calls than ps or pgrep would under most modes of operation.

    One optimization that I'd expect to help based on observed syscall behavior is reading from files in /proc with a larger buffer size.

    The below is what I see for reading from /proc/some-program-pid/environ:

    read(4, "LS_COLORS=rs=0:di=01;34:ln=01;36", 32) = 32
    read(4, ":mh=00:pi=40;33:so=01;35:do=01;3"..., 64) = 64
    read(4, "31;01:su=37;41:sg=30;43:ca=30;41"..., 128) = 128
    read(4, ":*.lzma=01;31:*.tlz=01;31:*.txz="..., 256) = 256
    read(4, "1:*.rz=01;31:*.jpg=01;35:*.jpeg="..., 512) = 512
    read(4, ".gl=01;35:*.dl=01;35:*.webm=01;3"..., 1024) = 1024
    ...
    

    This ends up being around eight or nine syscalls where a single one would do if we used a reasonable buffer size like 16384. If we want to avoid oversized Vecs, we can read into a stack buffer and copy into a Vec; this would still be much faster than suffering syscall overhead.

    In addition, it might be possible to refactor the API so that creating a sysinfo::System does no system calls (in much the same way Vec::new()does no allocation) and add options to refresh_all to specify which pieces of data to read. This would decrease the number of entries hit in each /proc entry and should also significantly decrease the number of system calls made.

    If these ideas sound reasonable I can write a patch.

    opened by sp3d 16
  • Add support for get temperature on m1

    Add support for get temperature on m1

    Hi, I trying to help with this issue #456, and it almost work, but I am a newbie to rust and not familiar with MacOS development. when I run the code on my m1 mac, I got 63 sensors' value, but some of are duplicated, like there are 4 sensors with name PMU tdie1, and I do not known if it is right, so I need some help with this.

    PMU tdie10: 39.083206°C (max: 0°C)
    PMU tdie7: 39.260803°C (max: 0°C)
    PMU TP2s: 38.9944°C (max: 0°C)
    NAND CH0 temp: 35°C (max: 0°C)
    PMU tdev1: 37.094604°C (max: 0°C)
    PMU tdie10: 38.816803°C (max: 0°C)
    PMU TP3g: 39.172012°C (max: 0°C)
    PMU tdev4: 35.31082°C (max: 0°C)
    PMU TP2s: 39.260803°C (max: 0°C)
    PMU tdev7: 37.319824°C (max: 0°C)
    PMU TP3g: 38.9944°C (max: 0°C)
    PMU tdev4: 35.391907°C (max: 0°C)
    PMU tdie2: 39.083206°C (max: 0°C)
    PMU tdev7: 38.099106°C (max: 0°C)
    gas gauge battery: 34°C (max: 0°C)
    PMU tdie2: 39.083206°C (max: 0°C)
    PMU tdie2: 39.172012°C (max: 0°C)
    gas gauge battery: 34.299988°C (max: 0°C)
    PMU tdie5: 39.260803°C (max: 0°C)
    PMU tdie2: 39.260803°C (max: 0°C)
    PMU tdie8: 39.083206°C (max: 0°C)
    PMU tdie5: 38.728012°C (max: 0°C)
    PMU TP0s: 39.172012°C (max: 0°C)
    PMU tdie8: 39.79361°C (max: 0°C)
    PMU TP1g: 39.260803°C (max: 0°C)
    PMU tdev2: 38.38739°C (max: 0°C)
    PMU TP0s: 39.172012°C (max: 0°C)
    PMU tcal: 51.850006°C (max: 0°C)
    PMU tdev5: 38.60811°C (max: 0°C)
    PMU TP1g: 39.260803°C (max: 0°C)
    PMU tdev2: 38.099106°C (max: 0°C)
    PMU tdev8: 36.41443°C (max: 0°C)
    PMU tdev5: 37.27928°C (max: 0°C)
    gas gauge battery: 34.299988°C (max: 0°C)
    PMU tdie0: 39.172012°C (max: 0°C)
    PMU tdev8: 37.01802°C (max: 0°C)
    gas gauge battery: 34.299988°C (max: 0°C)
    PMU tdie3: 39.172012°C (max: 0°C)
    PMU tdie0: 39.260803°C (max: 0°C)
    PMU tdie6: 39.260803°C (max: 0°C)
    PMU tdie3: 38.90561°C (max: 0°C)
    PMU tdie9: 39.616013°C (max: 0°C)
    PMU tdie6: 39.083206°C (max: 0°C)
    PMU TP1s: 39.4384°C (max: 0°C)
    PMU tcal: 51.850006°C (max: 0°C)
    PMU tdie9: 39.34961°C (max: 0°C)
    PMU TP2g: 39.083206°C (max: 0°C)
    PMU tdev3: 37.90091°C (max: 0°C)
    PMU TP1s: 39.083206°C (max: 0°C)
    PMU tdev1: 37.707214°C (max: 0°C)
    PMU tdev6: 37.477478°C (max: 0°C)
    PMU TP2g: 39.083206°C (max: 0°C)
    PMU tdev3: 37.27928°C (max: 0°C)
    PMU tdie1: 39.260803°C (max: 0°C)
    PMU tdev6: 36.463974°C (max: 0°C)
    gas gauge battery: 33°C (max: 0°C)
    PMU tdie1: 39.083206°C (max: 0°C)
    PMU tdie1: 39.260803°C (max: 0°C)
    gas gauge battery: 33.899994°C (max: 0°C)
    PMU tdie4: 39.172012°C (max: 0°C)
    PMU tdie1: 39.260803°C (max: 0°C)
    PMU tdie7: 38.728012°C (max: 0°C)
    PMU tdie4: 39.260803°C (max: 0°C)
    
    opened by Mark3K 15
  • Fail to build 0.21.1 on NetBSD

    Fail to build 0.21.1 on NetBSD

    Hi,

    I've been maintaning nushell for NetBSD and using it myself from 0.34.0 through to 0.40.0 but, now I can not build 0.41.0 since, sysinfo fails to build which is rather unfortunate.

    Here's the error, as reported on nushell, https://github.com/nushell/nushell/issues/4191

    error[E0433]: failed to resolve: use of undeclared crate or module `fmt`
      --> /usr/pkgsrc/wip/nushell/work/vendor/sysinfo-0.21.1/src/unknown/process.rs:11:6
       |
    11 | impl fmt::Display for ProcessStatus {
       |      ^^^ use of undeclared crate or module `fmt`
    
    error[E0433]: failed to resolve: use of undeclared crate or module `fmt`
      --> /usr/pkgsrc/wip/nushell/work/vendor/sysinfo-0.21.1/src/unknown/process.rs:12:27
       |
    12 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       |                           ^^^ use of undeclared crate or module `fmt`
    
    error[E0433]: failed to resolve: use of undeclared crate or module `fmt`
      --> /usr/pkgsrc/wip/nushell/work/vendor/sysinfo-0.21.1/src/unknown/process.rs:12:46
       |
    12 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       |                                              ^^^ use of undeclared crate or module `fmt`
    
    error[E0412]: cannot find type `ProcessStatus` in this scope
      --> /usr/pkgsrc/wip/nushell/work/vendor/sysinfo-0.21.1/src/unknown/process.rs:11:23
       |
    11 | impl fmt::Display for ProcessStatus {
       |                       ^^^^^^^^^^^^^ not found in this scope
       |
    help: consider importing this enum
       |
    7  | use crate::ProcessStatus;
       |
    
    error[E0412]: cannot find type `ProcessStatus` in this scope
      --> /usr/pkgsrc/wip/nushell/work/vendor/sysinfo-0.21.1/src/unknown/process.rs:73:25
       |
    73 |     fn status(&self) -> ProcessStatus {
       |                         ^^^^^^^^^^^^^ not found in this scope
       |
    help: consider importing this enum
       |
    7  | use crate::ProcessStatus;
       |
    
    error[E0433]: failed to resolve: use of undeclared type `ProcessStatus`
      --> /usr/pkgsrc/wip/nushell/work/vendor/sysinfo-0.21.1/src/unknown/process.rs:74:9
       |
    74 |         ProcessStatus::Unknown(0)
       |         ^^^^^^^^^^^^^ not found in this scope
       |
    help: consider importing this enum
       |
    7  | use crate::ProcessStatus;
       |
    
    Some errors have detailed explanations: E0412, E0433.
    For more information about an error, try `rustc --explain E0412`.
    error: could not compile `sysinfo` due to 6 previous errors
    

    Anything which can be done about it? I would really like to have sysinfo support improved for NetBSD and it's something I've been wondering how to help. Unfortunately, it feels over my skills to do something like this but, if you have some guidance to provide, I'd be happy to help.

    opened by 0323pin 15
  • [DRAFT] Serde implementation

    [DRAFT] Serde implementation

    This is a draft PR for implementing some serde support for this library as requested in #735. It introduces a feature that can be enabled during compilation by passing in the feature flag serde. As of the start of the draft PR, I have it compiling successfully on linux for the linux platform files and common.rs. I plan to push more to this branch as I cover the other platforms. This is just to get initial feedback.

    opened by martintc 3
  • process.cpu_usage() is 0

    process.cpu_usage() is 0

    When I use the following code to get the cpu usage of each process, it returns 0, both on windwos and mac

    use sysinfo::{NetworkExt, NetworksExt, ProcessExt, System, SystemExt};
    fn main() {
        let mut sys = System::new_all();
        sys.refresh_all();
        for (pid, process) in sys.processes() {
            println!("[{}] {} {} ", pid, process.name(), process.cpu_usage());
        }
    }
    

    sysinfo: 0.27.1 mac intel/arm64 windows

    bug windows freebsd mac 
    opened by polin-x 4
  • Unpredictable failures of test_wait_non_child on Debian CI on arm*

    Unpredictable failures of test_wait_non_child on Debian CI on arm*

    In Debian CI ee have been encoutering failures of test_wait_non_child for armel armhf and arm64. It doesn't fail every time and indeed it passes more often then it fails but it's still enough to cause annoying pseudo-regressions on our CI.

     ---- test_wait_non_child stdout ----
     thread 'test_wait_non_child' panicked at 'assertion failed: before.elapsed() > std::time::Duration::from_millis(2000)', tests/process.rs:457:5
     stack backtrace:
        0: rust_begin_unwind
                  at /usr/src/rustc-1.63.0/library/std/src/panicking.rs:584:5
        1: core::panicking::panic_fmt
                  at /usr/src/rustc-1.63.0/library/core/src/panicking.rs:142:14
        2: core::panicking::panic
             at /usr/src/rustc-1.63.0/library/core/src/panicking.rs:48:5
        3: process::test_wait_non_child
                  at ./tests/process.rs:457:5
        4: process::test_wait_non_child::{{closure}}
                  at ./tests/process.rs:425:1
        5: core::ops::function::FnOnce::call_once
                  at /usr/src/rustc-1.63.0/library/core/src/ops/function.rs:248:5
        6: core::ops::function::FnOnce::call_once
                  at /usr/src/rustc-1.63.0/library/core/src/ops/function.rs:248:5
     note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    

    When I look at the code, I notice that "before" is set after spawning the sleep process, so if there is even a relatively mild load spike after spawning the processes but before setting "before" then the elapsed time could be less than two seconds.

    I see two possible approaches to improving this.

    1. Relax the lower bound on the elapsed time.
    2. Move the setting of before, to before spawning the process.

    I prepared a patch that did both of these things and also added the actual elapsed time value to the assert messages. I have uploaded it to Debian. It can be found at https://salsa.debian.org/rust-team/debcargo-conf/-/blob/master/src/sysinfo/debian/patches/fix-race-in-test-wait-non-child.diff

    opened by plugwash 1
  • Process data inconsistency between `refresh_processes_specifics` and `refresh_process_specifics`

    Process data inconsistency between `refresh_processes_specifics` and `refresh_process_specifics`

    Thanks for all your work on sysinfo!

    I have found a way to get inconsistent data (or at least inconsistent process names) regarding a given process:

    • system.refresh_processes_specifics() (without any PID given) uses NtQuerySystemInformation and uses SYSTEM_PROCESS_INFORMATION.ImageName as their process names
    • system.refresh_process_specifics(pid) uses OpenProcess/NtQueryInformationProcess/EnumProcessModulesEx/GetModuleBaseNameW

    These two code paths may end up getting different results. See this minimal reproducer:

    use sysinfo::{Pid, PidExt, System, SystemExt, ProcessExt};
    
    fn main() {
        let mut system = System::default();
        system.refresh_processes_specifics(Default::default());
        for (pid, process) in system.processes() {
            let proc_name = process.name();
            if proc_name.contains("msiexec") {
                println!("  * {}\t{}\t{}\t{:?}", pid,
                    proc_name,
                    get_specific_proc_name(process.pid().as_u32()),
                    process.cmd()
                );
            }
        }
    }
    
    fn get_specific_proc_name(pid: u32) -> String {
        let s_pid = Pid::from_u32(pid);
        let mut system = System::default();
        system.refresh_process_specifics(s_pid, Default::default());
        let proc = system.process(s_pid).unwrap();
        proc.name().to_string()
    }
    

    This can display

      * 1512        msiexec.exe     msiexec.exe     ["C:\\Windows\\System32\\msiexec.exe", "/i", "P:\\webex\\meetings.msi"]
      * 4576        msiexec.exe     MsiExec.exe     ["C:\\Windows\\syswow64\\MsiExec.exe", "-Embedding", "CF3EB87457D3F802DE535DC782B0A689", "C"]
      * 4876        msiexec.exe     msiexec.exe     ["C:\\Windows\\system32\\msiexec.exe", "/V"]
    

    Mind the lower/uppercase inconsistency for process 4576 (which may be due to the erroneous command-line for a file that is actually named a lowercase C:\\Windows\\syswow64\\msiexec.exe)

    This is not a critical issue, because:

    • Windows is not supposed to be case-sensitive for process names (I suppose?)
    • sysinfo documentation discourages against re-creating several System instances. Re-using the same instance would probably detect it knows this PID already and avoid the whole OpenProcess/NtQueryInformationProcess/EnumProcessModulesEx/GetModuleBaseNameW
    • it does not look this happens often (I had a hard time re-producing it, as the easiest reproducer I made involves running a 32-bit MSI on a 64-bit machine.

    But still, having two different code paths to get the same data may look like something to avoid (if ever that would be possible).

    What's your opinion on this? I may try to fix it myself in case you'd like me to (although I'm not familiar (yet?) with sysinfo).

    enhancement windows 
    opened by daladim 11
  • Getting process info in FreeBSD can emit errors to stderr

    Getting process info in FreeBSD can emit errors to stderr

    Description

    It seems like trying to get process info using sysinfo on FreeBSD systems can cause unexpected errors to get printed in stderr of the form:

    kinfo_getfile(): No such process
    

    This is a bit problematic in some instances, such as TUI apps since it can start drawing over the interface.

    I tried narrowing down where it was coming from, and I could be wrong but it seems like the problematic line is in freebsd/system.rs at line 768:

    let head = libc::procstat_getfiles(self.procstat, kproc as *const _ as usize as *mut _, 0);
    

    Unfortunately, I don't know if there's a good workaround or pre-check to prevent this. I saw in your blog that procstat_getfiles was used in place of sysctl due to it not returning errors, the linked bugzilla bug seems to have gotten some related updates if that helps.

    Reproducing

    This can be reproduced by running the simple example on a FreeBSD VM (I used GhostBSD), which has this error on startup for me:

    simple: kinfo_getfile(): No such process
    
    freebsd 
    opened by ClementTsang 5
Owner
Guillaume Gomez
Opensource lover. Rustdoc team leader, member of the Rust dev-tools, documentation and docs.rs teams, GNOME foundation member.
Guillaume Gomez
Basic system information fetcher, with a focus on performance.

Table of Contents: About Changelog Dependencies Benchmarks Features Installation Platform Support About Macchina Macchina lets you view basic system i

null 677 Dec 28, 2022
A TUI system monitor written in Rust

NO LONGER MAINTAINED. For a similar program, check out https://github.com/ClementTsang/bottom. ytop Another TUI based system monitor, this time in Rus

Caleb Bassi 2.1k Jan 3, 2023
A lib crate for gathering system info such as cpu, distro, environment, kernel, etc in Rust.

nixinfo A lib crate for gathering system info such as cpu, distro, environment, kernel, etc in Rust. To use: nixinfo = "0.2.8" in your Cargo.toml. Cur

ValleyKnight 37 Nov 26, 2022
System Tools with real-time Web UI

HeroicToys The remake of useful CLI tools, but with Web UI. The project uses RillRate - Dynamic UI for bots, microservices, and IoT.

RillRate 27 Nov 10, 2022
System Tools with real-time Web UI

MultiTool System Tools with real-time Web UI. The project uses RillRate - Dynamic UI for bots, microservices, and IoT. Included Implemented: System Mo

RillRate 27 Nov 10, 2022
Cap'n Proto is a type system for distributed systems

Cap'n Proto for Rust documentation blog Introduction Cap'n Proto is a type system for distributed systems. With Cap'n Proto, you describe your data an

Cap'n Proto 1.5k Jan 1, 2023
A simple and fast download accelerator, written in Rust

zou A simple and fast download accelerator, written in Rust Zou is a Snatch fork by @k0pernicus. Snatch is a fast and interruptable download accelerat

Antonin Carette 173 Dec 4, 2022
A modern replacement for ps written in Rust

procs procs is a replacement for ps written in Rust. Documentation quick links Features Platform Installation Usage Configuration Features Output by t

null 3.6k Jan 5, 2023
Blazing 💥 fast terminal-ui for git written in rust 🦀

Blazing fast terminal client for git written in Rust Features Fast and intuitive keyboard only control Context based help (no need to memorize tons of

Stephan Dilly 11.8k Jan 5, 2023
A bash-like Unix shell written in Rust

Cicada Unix Shell Cicada is a simple Unix shell written in Rust. Documents Install cicada Environment Variables Cicada Builtins Completion RC File His

Hugo Wang 921 Dec 28, 2022
Performs distributed command execution, written in Rust w/ Tokio

Concurr: Distributed and Concurrent Command Execution, in Rust This project is dual licensed under MIT and Apache 2.0. Originally inspired by the GNU

Michael Murphy 93 Dec 18, 2022
A non-root version of traceroute written in Rust

tracepath-rs A non-root version of traceroute written in Rust for Linux.

Peter Malmgren 9 Dec 30, 2022
Dancing Links (“dlx”) solver for the exact cover problem, written in Rust. Can be used to create a sudoku solver.

Dancing Links “dlx” Dancing Links solver for “algorithm X” by Knuth This solver solves the exact cover problem using “algorithm X”, implemented using

bluss 4 Nov 19, 2022
LeftHK - A hotkey daemon written in Rust

LeftHK LeftHK - A hotkey daemon written in Rust THIS IS BETA SOFTWARE The configuration file should be created in ~/.config/lefthk/ and called config.

null 15 Oct 12, 2022
Untrusted IPC with maximum performance and minimum latency. On Rust, on Linux.

Untrusted IPC with maximum performance and minimum latency. On Rust, on Linux. When is this Rust crate useful? Performance or latency is crucial, and

null 72 Jan 3, 2023
OCI Runtime, Image and Distribution Spec in Rust

oci-spec-rs Open Container Initiative (OCI) Specifications for Rust This library provides a convenient way to interact with the specifications defined

Containers 119 Dec 29, 2022
desktop automation, screen capture, input listen/simulation, asar compress, color picker for nodejs and electron based on rust

desktop automation, screen capture, input listen/simulation, asar compress, color picker for nodejs and electron based on rust. 基于 Rust / WASM 提供截图、取色、键鼠事件监听模拟、压缩解压、图像处理、获取已安装应用等跨平台功能的现代异步 Nodejs 模块,占用空间小, 安装便捷, 使用简单, 高性能, 资源占用极小, 可取代 iohook 和 robotjs

null 48 Dec 15, 2022
GTK application for browsing and installing fonts from Google's font archive

Font Finder This project is a from-scratch implementation of TypeCatcher in Rust. It is a GTK3 application for browsing through and installing fonts f

Michael Murphy 252 Dec 26, 2022
Linux Kernel Manager and Activity Monitor 🐧💻

Linux Kernel Manager and Activity Monitor ?? ?? The kernel is the part of the operating system that facilitates interactions between hardware and soft

Orhun Parmaksız 1.7k Jan 5, 2023