1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-20 03:09:06 +03:00

mux: remove sysinfo dep on linux

This commit is contained in:
Wez Furlong 2021-12-31 16:15:19 -07:00
parent 3eb5408135
commit 259c78d514
4 changed files with 140 additions and 8 deletions

View File

@ -38,10 +38,8 @@ url = "2"
wezterm-ssh = { path = "../wezterm-ssh" }
wezterm-term = { path = "../term", features=["use_serde"] }
[target.'cfg(any(windows, target_os="linux"))'.dependencies]
sysinfo = "0.22"
[target."cfg(windows)".dependencies]
sysinfo = "0.22"
winapi = { version = "0.3", features = [
"handleapi",
"processthreadsapi"

View File

@ -836,10 +836,15 @@ impl LocalPane {
fn divine_process_list(&self, _force_refresh: bool) -> Option<LocalProcessInfo> {
#[cfg(target_os = "macos")]
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
return dbg!(LocalProcessInfo::with_root_pid_macos(*pid));
return LocalProcessInfo::with_root_pid_macos(*pid);
}
#[cfg(any(windows, target_os = "linux"))]
#[cfg(target_os = "linux")]
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
return LocalProcessInfo::with_root_pid_linux(*pid);
}
#[cfg(windows)]
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
return LocalProcessInfo::with_root_pid(
&*if _force_refresh {

View File

@ -18,7 +18,7 @@ pub enum LocalProcessStatus {
Unknown,
}
#[cfg(any(windows, target_os = "linux"))]
#[cfg(windows)]
impl LocalProcessStatus {
fn from_process_status(status: sysinfo::ProcessStatus) -> Self {
match status {
@ -38,6 +38,25 @@ impl LocalProcessStatus {
}
}
#[cfg(target_os = "linux")]
impl From<&str> for LocalProcessStatus {
fn from(s: &str) -> Self {
match s {
"R" => Self::Run,
"S" => Self::Sleep,
"D" => Self::Idle,
"Z" => Self::Zombie,
"T" => Self::Stop,
"t" => Self::Tracing,
"X" | "x" => Self::Dead,
"K" => Self::Wakekill,
"W" => Self::Waking,
"P" => Self::Parked,
_ => Self::Unknown,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct LocalProcessInfo {
pub pid: u32,
@ -70,6 +89,116 @@ impl LocalProcessInfo {
}
}
#[cfg(target_os = "linux")]
impl LocalProcessInfo {
pub(crate) fn with_root_pid_linux(pid: u32) -> Option<Self> {
use libc::pid_t;
let pid = pid as pid_t;
fn all_pids() -> Vec<pid_t> {
let mut pids = vec![];
if let Ok(dir) = std::fs::read_dir("/proc") {
for entry in dir {
if let Ok(entry) = entry {
if let Ok(file_type) = entry.file_type() {
if file_type.is_dir() {
if let Some(name) = entry.file_name().to_str() {
if let Ok(pid) = name.parse::<pid_t>() {
pids.push(pid);
}
}
}
}
}
}
}
pids
}
struct LinuxStat {
pid: pid_t,
name: String,
status: String,
ppid: pid_t,
// Time process started after boot, measured in ticks
starttime: u64,
}
fn info_for_pid(pid: pid_t) -> Option<LinuxStat> {
let data = std::fs::read_to_string(format!("/proc/{}/stat", pid)).ok()?;
let (_pid_space, name) = data.split_once('(')?;
let (name, fields) = name.rsplit_once(')')?;
let fields = fields.split_whitespace().collect::<Vec<_>>();
Some(LinuxStat {
pid,
name: name.to_string(),
status: fields.get(0)?.to_string(),
ppid: fields.get(1)?.parse().ok()?,
starttime: fields.get(20)?.parse().ok()?,
})
}
fn exe_for_pid(pid: pid_t) -> PathBuf {
std::fs::read_link(format!("/proc/{}/exe", pid)).unwrap_or_else(|_| PathBuf::new())
}
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,
Err(_) => return vec![],
};
let mut args = vec![];
let data = data.strip_suffix(&[0]).unwrap_or(&data);
for arg in data.split(|&c| c == 0) {
args.push(String::from_utf8_lossy(arg).to_owned().to_string());
}
args
}
let procs: Vec<_> = all_pids().into_iter().filter_map(info_for_pid).collect();
fn build_proc(info: &LinuxStat, procs: &[LinuxStat]) -> LocalProcessInfo {
let mut children = HashMap::new();
for kid in procs {
if kid.ppid == info.pid {
children.insert(kid.pid as u32, build_proc(kid, procs));
}
}
let executable = exe_for_pid(info.pid);
let name = info.name.clone();
let argv = parse_cmdline(info.pid);
LocalProcessInfo {
pid: info.pid as _,
ppid: info.ppid as _,
name,
executable,
cwd: cwd_for_pid(info.pid),
argv,
start_time: info.starttime,
status: info.status.as_str().into(),
children,
}
}
if let Some(info) = procs.iter().find(|info| info.pid == 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> {
@ -271,7 +400,7 @@ impl LocalProcessInfo {
}
}
#[cfg(any(windows, target_os = "linux"))]
#[cfg(windows)]
impl LocalProcessInfo {
pub(crate) fn with_root_pid(system: &sysinfo::System, pid: u32) -> Option<Self> {
use sysinfo::{AsU32, Pid, Process, ProcessExt, SystemExt};

View File

@ -1,4 +1,4 @@
#![cfg(any(windows, target_os = "linux"))]
#![cfg(windows)]
use std::sync::{Mutex, MutexGuard};
use std::time::{Duration, Instant};
use sysinfo::{ProcessRefreshKind, RefreshKind, System, SystemExt};