mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
mux: remove dep on sysinfo; we now do our own win32 stuff
This also removes the sysinfo cache; will replace it with something else in a follow up commit.
This commit is contained in:
parent
2b38c3dd32
commit
2aa491af1a
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -2292,6 +2292,7 @@ dependencies = [
|
||||
"luahelper",
|
||||
"metrics",
|
||||
"mlua",
|
||||
"ntapi",
|
||||
"portable-pty",
|
||||
"promise",
|
||||
"rangeset",
|
||||
@ -2299,7 +2300,6 @@ dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
"smol",
|
||||
"sysinfo",
|
||||
"terminfo",
|
||||
"termwiz",
|
||||
"textwrap 0.14.2",
|
||||
@ -3944,21 +3944,6 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b645b59c59114c25d3d554f781b0a1f1f01545d1d02f271bfb1c897bdfdfdcf3"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"core-foundation-sys 0.8.3",
|
||||
"libc",
|
||||
"ntapi",
|
||||
"once_cell",
|
||||
"rayon",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabout"
|
||||
version = "0.3.0"
|
||||
|
@ -39,10 +39,13 @@ wezterm-ssh = { path = "../wezterm-ssh" }
|
||||
wezterm-term = { path = "../term", features=["use_serde"] }
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
sysinfo = "0.22"
|
||||
ntapi = "0.3"
|
||||
winapi = { version = "0.3", features = [
|
||||
"handleapi",
|
||||
"processthreadsapi"
|
||||
"memoryapi",
|
||||
"psapi",
|
||||
"processthreadsapi",
|
||||
"tlhelp32",
|
||||
]}
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -32,7 +32,6 @@ pub mod pane;
|
||||
pub mod procinfo;
|
||||
pub mod renderable;
|
||||
pub mod ssh;
|
||||
mod sysinfo;
|
||||
pub mod tab;
|
||||
pub mod termwiztermtab;
|
||||
pub mod tmux;
|
||||
|
@ -844,6 +844,12 @@ impl LocalPane {
|
||||
return LocalProcessInfo::with_root_pid_linux(*pid);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
|
||||
return dbg!(LocalProcessInfo::with_root_pid_windows(*pid));
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(windows)]
|
||||
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
|
||||
return LocalProcessInfo::with_root_pid(
|
||||
@ -855,6 +861,7 @@ impl LocalPane {
|
||||
*pid,
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
None
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
|
||||
pub enum LocalProcessStatus {
|
||||
@ -18,26 +19,6 @@ pub enum LocalProcessStatus {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl LocalProcessStatus {
|
||||
fn from_process_status(status: sysinfo::ProcessStatus) -> Self {
|
||||
match status {
|
||||
sysinfo::ProcessStatus::Idle => Self::Idle,
|
||||
sysinfo::ProcessStatus::Run => Self::Run,
|
||||
sysinfo::ProcessStatus::Sleep => Self::Sleep,
|
||||
sysinfo::ProcessStatus::Stop => Self::Stop,
|
||||
sysinfo::ProcessStatus::Zombie => Self::Zombie,
|
||||
sysinfo::ProcessStatus::Tracing => Self::Tracing,
|
||||
sysinfo::ProcessStatus::Dead => Self::Dead,
|
||||
sysinfo::ProcessStatus::Wakekill => Self::Wakekill,
|
||||
sysinfo::ProcessStatus::Waking => Self::Waking,
|
||||
sysinfo::ProcessStatus::Parked => Self::Parked,
|
||||
sysinfo::ProcessStatus::LockBlocked => Self::LockBlocked,
|
||||
sysinfo::ProcessStatus::Unknown(_) => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
impl From<&str> for LocalProcessStatus {
|
||||
fn from(s: &str) -> Self {
|
||||
@ -81,7 +62,7 @@ pub struct LocalProcessInfo {
|
||||
pub cwd: PathBuf,
|
||||
pub status: LocalProcessStatus,
|
||||
pub children: HashMap<u32, LocalProcessInfo>,
|
||||
pub start_time: u64,
|
||||
pub start_time: SystemTime,
|
||||
}
|
||||
luahelper::impl_lua_conversion!(LocalProcessInfo);
|
||||
|
||||
@ -160,6 +141,7 @@ impl LocalProcessInfo {
|
||||
fn cwd_for_pid(pid: pid_t) -> PathBuf {
|
||||
std::fs::read_link(format!("/proc/{}/cwd", pid)).unwrap_or_else(|_| PathBuf::new())
|
||||
}
|
||||
|
||||
fn parse_cmdline(pid: pid_t) -> Vec<String> {
|
||||
let data = match std::fs::read(format!("/proc/{}/cmdline", pid)) {
|
||||
Ok(data) => data,
|
||||
@ -213,6 +195,390 @@ impl LocalProcessInfo {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl LocalProcessInfo {
|
||||
pub(crate) fn with_root_pid_windows(pid: u32) -> Option<Self> {
|
||||
use ntapi::ntpebteb::PEB;
|
||||
use ntapi::ntpsapi::{
|
||||
NtQueryInformationProcess, ProcessBasicInformation, ProcessWow64Information,
|
||||
PROCESS_BASIC_INFORMATION,
|
||||
};
|
||||
use ntapi::ntrtl::RTL_USER_PROCESS_PARAMETERS;
|
||||
use ntapi::ntwow64::RTL_USER_PROCESS_PARAMETERS32;
|
||||
use std::ffi::OsString;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use winapi::shared::minwindef::{FILETIME, HMODULE, LPVOID, MAX_PATH};
|
||||
use winapi::shared::ntdef::{FALSE, NT_SUCCESS};
|
||||
use winapi::um::handleapi::CloseHandle;
|
||||
use winapi::um::memoryapi::ReadProcessMemory;
|
||||
use winapi::um::processthreadsapi::{GetProcessTimes, OpenProcess};
|
||||
use winapi::um::psapi::{EnumProcessModulesEx, GetModuleFileNameExW, LIST_MODULES_ALL};
|
||||
use winapi::um::shellapi::CommandLineToArgvW;
|
||||
use winapi::um::tlhelp32::*;
|
||||
use winapi::um::winbase::LocalFree;
|
||||
use winapi::um::winnt::{HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ};
|
||||
|
||||
struct Snapshot(HANDLE);
|
||||
|
||||
impl Snapshot {
|
||||
pub fn new() -> Option<Self> {
|
||||
let handle = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
|
||||
if handle.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Self(handle))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> ProcIter {
|
||||
ProcIter {
|
||||
snapshot: &self,
|
||||
first: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Snapshot {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CloseHandle(self.0) };
|
||||
}
|
||||
}
|
||||
|
||||
struct ProcIter<'a> {
|
||||
snapshot: &'a Snapshot,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ProcIter<'a> {
|
||||
type Item = PROCESSENTRY32W;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut entry: PROCESSENTRY32W = unsafe { std::mem::zeroed() };
|
||||
entry.dwSize = std::mem::size_of::<PROCESSENTRY32W>() as _;
|
||||
let res = if self.first {
|
||||
self.first = false;
|
||||
unsafe { Process32FirstW(self.snapshot.0, &mut entry) }
|
||||
} else {
|
||||
unsafe { Process32NextW(self.snapshot.0, &mut entry) }
|
||||
};
|
||||
if res == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let snapshot = Snapshot::new()?;
|
||||
let procs: Vec<_> = snapshot.iter().collect();
|
||||
|
||||
fn wstr_to_path(slice: &[u16]) -> PathBuf {
|
||||
match slice.iter().position(|&c| c == 0) {
|
||||
Some(nul) => OsString::from_wide(&slice[..nul]),
|
||||
None => OsString::from_wide(slice),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
fn wstr_to_string(slice: &[u16]) -> String {
|
||||
wstr_to_path(slice).to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
struct ProcParams {
|
||||
argv: Vec<String>,
|
||||
cwd: PathBuf,
|
||||
}
|
||||
|
||||
struct ProcHandle(HANDLE);
|
||||
impl ProcHandle {
|
||||
fn new(pid: u32) -> Option<Self> {
|
||||
let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
|
||||
let handle = unsafe { OpenProcess(options, FALSE as _, pid) };
|
||||
if handle.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(Self(handle))
|
||||
}
|
||||
|
||||
fn hmodule(&self) -> Option<HMODULE> {
|
||||
let mut needed = 0;
|
||||
let mut hmod = [0 as HMODULE];
|
||||
let size = std::mem::size_of_val(&hmod);
|
||||
let res = unsafe {
|
||||
EnumProcessModulesEx(
|
||||
self.0,
|
||||
hmod.as_mut_ptr(),
|
||||
size as _,
|
||||
&mut needed,
|
||||
LIST_MODULES_ALL,
|
||||
)
|
||||
};
|
||||
if res == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(hmod[0])
|
||||
}
|
||||
}
|
||||
|
||||
fn executable(&self) -> Option<PathBuf> {
|
||||
let hmod = self.hmodule()?;
|
||||
let mut buf = [0u16; MAX_PATH + 1];
|
||||
let res =
|
||||
unsafe { GetModuleFileNameExW(self.0, hmod, buf.as_mut_ptr(), buf.len() as _) };
|
||||
if res == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(wstr_to_path(&buf))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_peb32_addr(&self) -> Option<LPVOID> {
|
||||
let mut peb32_addr = MaybeUninit::<LPVOID>::uninit();
|
||||
let res = unsafe {
|
||||
NtQueryInformationProcess(
|
||||
self.0,
|
||||
ProcessWow64Information,
|
||||
peb32_addr.as_mut_ptr() as _,
|
||||
std::mem::size_of::<LPVOID>() as _,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if !NT_SUCCESS(res) {
|
||||
return None;
|
||||
}
|
||||
let peb32_addr = unsafe { peb32_addr.assume_init() };
|
||||
if peb32_addr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(peb32_addr)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_params(&self) -> Option<ProcParams> {
|
||||
match self.get_peb32_addr() {
|
||||
Some(peb32) => self.get_params_32(peb32),
|
||||
None => self.get_params_64(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_basic_info(&self) -> Option<PROCESS_BASIC_INFORMATION> {
|
||||
let mut info = MaybeUninit::<PROCESS_BASIC_INFORMATION>::uninit();
|
||||
let res = unsafe {
|
||||
NtQueryInformationProcess(
|
||||
self.0,
|
||||
ProcessBasicInformation,
|
||||
info.as_mut_ptr() as _,
|
||||
std::mem::size_of::<PROCESS_BASIC_INFORMATION>() as _,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if !NT_SUCCESS(res) {
|
||||
return None;
|
||||
}
|
||||
let info = unsafe { info.assume_init() };
|
||||
Some(info)
|
||||
}
|
||||
|
||||
fn read_struct<T>(&self, addr: LPVOID) -> Option<T> {
|
||||
let mut data = MaybeUninit::<T>::uninit();
|
||||
let res = unsafe {
|
||||
ReadProcessMemory(
|
||||
self.0,
|
||||
addr as _,
|
||||
data.as_mut_ptr() as _,
|
||||
std::mem::size_of::<T>() as _,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if res == 0 {
|
||||
return None;
|
||||
}
|
||||
let data = unsafe { data.assume_init() };
|
||||
Some(data)
|
||||
}
|
||||
|
||||
fn get_peb(&self, info: &PROCESS_BASIC_INFORMATION) -> Option<PEB> {
|
||||
self.read_struct(info.PebBaseAddress as _)
|
||||
}
|
||||
|
||||
fn get_proc_params(&self, peb: &PEB) -> Option<RTL_USER_PROCESS_PARAMETERS> {
|
||||
self.read_struct(peb.ProcessParameters as _)
|
||||
}
|
||||
|
||||
fn get_params_64(&self) -> Option<ProcParams> {
|
||||
let info = self.get_basic_info()?;
|
||||
let peb = self.get_peb(&info)?;
|
||||
let params = self.get_proc_params(&peb)?;
|
||||
|
||||
let cmdline = self.read_process_wchar(
|
||||
params.CommandLine.Buffer as _,
|
||||
params.CommandLine.Length as _,
|
||||
)?;
|
||||
let cwd = self.read_process_wchar(
|
||||
params.CurrentDirectory.DosPath.Buffer as _,
|
||||
params.CurrentDirectory.DosPath.Length as _,
|
||||
)?;
|
||||
|
||||
Some(ProcParams {
|
||||
argv: cmd_line_to_argv(&cmdline),
|
||||
cwd: wstr_to_path(&cwd),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_proc_params_32(&self, peb32: LPVOID) -> Option<RTL_USER_PROCESS_PARAMETERS32> {
|
||||
self.read_struct(peb32)
|
||||
}
|
||||
|
||||
fn get_params_32(&self, peb32: LPVOID) -> Option<ProcParams> {
|
||||
let params = self.get_proc_params_32(peb32)?;
|
||||
|
||||
let cmdline = self.read_process_wchar(
|
||||
params.CommandLine.Buffer as _,
|
||||
params.CommandLine.Length as _,
|
||||
)?;
|
||||
let cwd = self.read_process_wchar(
|
||||
params.CurrentDirectory.DosPath.Buffer as _,
|
||||
params.CurrentDirectory.DosPath.Length as _,
|
||||
)?;
|
||||
|
||||
Some(ProcParams {
|
||||
argv: cmd_line_to_argv(&cmdline),
|
||||
cwd: wstr_to_path(&cwd),
|
||||
})
|
||||
}
|
||||
|
||||
fn read_process_wchar(&self, ptr: LPVOID, size: usize) -> Option<Vec<u16>> {
|
||||
let mut buf = vec![0u16; size / 2];
|
||||
|
||||
let res = unsafe {
|
||||
ReadProcessMemory(
|
||||
self.0,
|
||||
ptr as _,
|
||||
buf.as_mut_ptr() as _,
|
||||
size,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if res == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(buf)
|
||||
}
|
||||
|
||||
fn start_time(&self) -> Option<SystemTime> {
|
||||
let mut start = FILETIME {
|
||||
dwLowDateTime: 0,
|
||||
dwHighDateTime: 0,
|
||||
};
|
||||
let mut exit = FILETIME {
|
||||
dwLowDateTime: 0,
|
||||
dwHighDateTime: 0,
|
||||
};
|
||||
let mut kernel = FILETIME {
|
||||
dwLowDateTime: 0,
|
||||
dwHighDateTime: 0,
|
||||
};
|
||||
let mut user = FILETIME {
|
||||
dwLowDateTime: 0,
|
||||
dwHighDateTime: 0,
|
||||
};
|
||||
let res = unsafe {
|
||||
GetProcessTimes(self.0, &mut start, &mut exit, &mut kernel, &mut user)
|
||||
};
|
||||
if res == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Units are 100 nanoseconds
|
||||
let start = (start.dwHighDateTime as u64) << 32 | start.dwLowDateTime as u64;
|
||||
let start = Duration::from_nanos(start * 100);
|
||||
|
||||
// Difference between the windows epoch and the unix epoch
|
||||
const WINDOWS_EPOCH: Duration = Duration::from_secs(11_644_473_600);
|
||||
|
||||
Some(SystemTime::UNIX_EPOCH + start - WINDOWS_EPOCH)
|
||||
}
|
||||
}
|
||||
|
||||
fn cmd_line_to_argv(buf: &[u16]) -> Vec<String> {
|
||||
let mut argc = 0;
|
||||
let argvp = unsafe { CommandLineToArgvW(buf.as_ptr(), &mut argc) };
|
||||
if argvp.is_null() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let argv = unsafe { std::slice::from_raw_parts(argvp, argc as usize) };
|
||||
let mut args = vec![];
|
||||
for &arg in argv {
|
||||
let len = unsafe { libc::wcslen(arg) };
|
||||
let arg = unsafe { std::slice::from_raw_parts(arg, len) };
|
||||
args.push(wstr_to_string(arg));
|
||||
}
|
||||
unsafe { LocalFree(argvp as _) };
|
||||
args
|
||||
}
|
||||
|
||||
impl Drop for ProcHandle {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CloseHandle(self.0) };
|
||||
}
|
||||
}
|
||||
|
||||
fn build_proc(info: &PROCESSENTRY32W, procs: &[PROCESSENTRY32W]) -> LocalProcessInfo {
|
||||
let mut children = HashMap::new();
|
||||
|
||||
for kid in procs {
|
||||
if kid.th32ParentProcessID == info.th32ProcessID {
|
||||
children.insert(kid.th32ProcessID, build_proc(kid, procs));
|
||||
}
|
||||
}
|
||||
|
||||
let mut executable = wstr_to_path(&info.szExeFile);
|
||||
|
||||
let name = match executable.file_name() {
|
||||
Some(name) => name.to_string_lossy().into_owned(),
|
||||
None => String::new(),
|
||||
};
|
||||
|
||||
let mut start_time = SystemTime::now();
|
||||
let mut cwd = PathBuf::new();
|
||||
let mut argv = vec![];
|
||||
|
||||
if let Some(proc) = ProcHandle::new(info.th32ProcessID) {
|
||||
if let Some(exe) = proc.executable() {
|
||||
executable = exe;
|
||||
}
|
||||
if let Some(params) = proc.get_params() {
|
||||
cwd = params.cwd;
|
||||
argv = params.argv;
|
||||
}
|
||||
if let Some(start) = proc.start_time() {
|
||||
start_time = start;
|
||||
}
|
||||
}
|
||||
|
||||
LocalProcessInfo {
|
||||
pid: info.th32ProcessID,
|
||||
ppid: info.th32ParentProcessID,
|
||||
name,
|
||||
executable,
|
||||
cwd,
|
||||
argv,
|
||||
start_time,
|
||||
status: LocalProcessStatus::Run,
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(info) = procs.iter().find(|info| info.th32ProcessID == pid) {
|
||||
Some(build_proc(info, &procs))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
impl LocalProcessInfo {
|
||||
pub(crate) fn with_root_pid_macos(pid: u32) -> Option<Self> {
|
||||
@ -410,40 +776,3 @@ impl LocalProcessInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl LocalProcessInfo {
|
||||
pub(crate) fn with_root_pid(system: &sysinfo::System, pid: u32) -> Option<Self> {
|
||||
use sysinfo::{AsU32, Pid, Process, ProcessExt, SystemExt};
|
||||
|
||||
fn build_proc(proc: &Process, processes: &HashMap<Pid, Process>) -> LocalProcessInfo {
|
||||
// Process has a `tasks` field but it does not correspond to child processes,
|
||||
// so we need to repeatedly walk the full process list and establish that
|
||||
// linkage for ourselves here
|
||||
let mut children = HashMap::new();
|
||||
let pid = proc.pid();
|
||||
for (child_pid, child_proc) in processes {
|
||||
if child_proc.parent() == Some(pid) {
|
||||
children.insert(child_pid.as_u32(), build_proc(child_proc, processes));
|
||||
}
|
||||
}
|
||||
|
||||
LocalProcessInfo {
|
||||
pid: proc.pid().as_u32(),
|
||||
ppid: proc.parent().map(|pid| pid.as_u32()).unwrap_or(1),
|
||||
name: proc.name().to_string(),
|
||||
executable: proc.exe().to_path_buf(),
|
||||
cwd: proc.cwd().to_path_buf(),
|
||||
argv: proc.cmd().to_vec(),
|
||||
start_time: proc.start_time(),
|
||||
status: LocalProcessStatus::from_process_status(proc.status()),
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
let proc = system.process(pid as Pid)?;
|
||||
let procs = system.processes();
|
||||
|
||||
Some(build_proc(&proc, &procs))
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
#![cfg(windows)]
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
use std::time::{Duration, Instant};
|
||||
use sysinfo::{ProcessRefreshKind, RefreshKind, System, SystemExt};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref SYSTEM: Mutex<CachedSystemInfo> = Mutex::new(CachedSystemInfo::new());
|
||||
}
|
||||
|
||||
pub struct CachedSystemInfo {
|
||||
last_update: Instant,
|
||||
system: sysinfo::System,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for CachedSystemInfo {
|
||||
type Target = sysinfo::System;
|
||||
|
||||
fn deref(&self) -> &sysinfo::System {
|
||||
&self.system
|
||||
}
|
||||
}
|
||||
|
||||
impl CachedSystemInfo {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
system: System::new_with_specifics(
|
||||
RefreshKind::new().with_processes(ProcessRefreshKind::new()),
|
||||
),
|
||||
last_update: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh_now(&mut self) {
|
||||
self.system
|
||||
.refresh_processes_specifics(ProcessRefreshKind::new());
|
||||
self.last_update = Instant::now();
|
||||
}
|
||||
|
||||
pub fn check_refresh(&mut self) {
|
||||
if self.last_update.elapsed() < Duration::from_millis(300) {
|
||||
return;
|
||||
}
|
||||
self.refresh_now();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get() -> MutexGuard<'static, CachedSystemInfo> {
|
||||
let mut guard = SYSTEM.lock().unwrap();
|
||||
guard.check_refresh();
|
||||
guard
|
||||
}
|
||||
|
||||
pub fn get_with_forced_refresh() -> MutexGuard<'static, CachedSystemInfo> {
|
||||
let mut guard = SYSTEM.lock().unwrap();
|
||||
guard.refresh_now();
|
||||
guard
|
||||
}
|
Loading…
Reference in New Issue
Block a user