mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 13:52:55 +03:00
mux: refactor sysinfo. Use own fn for macos foreground process path
I noticed that sysinfo failed to yield info about 50% of the time on macos! Just go direct to the underlying system function; we don't need all of the info that sysinfo collects in any case.
This commit is contained in:
parent
09e8d7b92f
commit
80d16574e3
@ -29,6 +29,7 @@ pub mod connui;
|
||||
pub mod domain;
|
||||
pub mod localpane;
|
||||
pub mod pane;
|
||||
pub mod procinfo;
|
||||
pub mod renderable;
|
||||
pub mod ssh;
|
||||
mod sysinfo;
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::domain::DomainId;
|
||||
use crate::pane::{CloseReason, Pane, PaneId, Pattern, SearchResult};
|
||||
use crate::procinfo::LocalProcessInfo;
|
||||
use crate::renderable::*;
|
||||
use crate::tmux::{TmuxDomain, TmuxDomainState};
|
||||
use crate::{Domain, Mux, MuxNotification};
|
||||
@ -9,13 +10,11 @@ use config::keyassignment::ScrollbackEraseMode;
|
||||
use config::{configuration, ExitBehavior};
|
||||
use portable_pty::{Child, ChildKiller, ExitStatus, MasterPty, PtySize};
|
||||
use rangeset::RangeSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smol::channel::{bounded, Receiver, TryRecvError};
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::io::Result as IoResult;
|
||||
use std::ops::Range;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use termwiz::escape::DeviceControlMode;
|
||||
use termwiz::surface::{Line, SequenceNo, SEQ_ZERO};
|
||||
@ -337,7 +336,27 @@ impl Pane for LocalPane {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_foreground_process_name(&self) -> Option<String> {
|
||||
let leader = self.pty.borrow().process_group_leader()?;
|
||||
|
||||
let mut buffer: Vec<u8> = Vec::with_capacity(libc::PROC_PIDPATHINFO_MAXSIZE as _);
|
||||
let x = unsafe {
|
||||
libc::proc_pidpath(
|
||||
leader,
|
||||
buffer.as_mut_ptr() as *mut _,
|
||||
libc::PROC_PIDPATHINFO_MAXSIZE as _,
|
||||
)
|
||||
};
|
||||
if x > 0 {
|
||||
unsafe { buffer.set_len(x as usize) };
|
||||
String::from_utf8(buffer).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "linux"))]
|
||||
fn get_foreground_process_name(&self) -> Option<String> {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
@ -836,111 +855,6 @@ impl LocalPane {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
|
||||
pub enum LocalProcessStatus {
|
||||
Idle,
|
||||
Run,
|
||||
Sleep,
|
||||
Stop,
|
||||
Zombie,
|
||||
Tracing,
|
||||
Dead,
|
||||
Wakekill,
|
||||
Waking,
|
||||
Parked,
|
||||
LockBlocked,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct LocalProcessInfo {
|
||||
pub pid: u32,
|
||||
pub ppid: u32,
|
||||
pub name: String,
|
||||
pub executable: PathBuf,
|
||||
pub argv: Vec<String>,
|
||||
pub cwd: PathBuf,
|
||||
pub status: LocalProcessStatus,
|
||||
pub children: HashMap<u32, LocalProcessInfo>,
|
||||
pub start_time: u64,
|
||||
}
|
||||
luahelper::impl_lua_conversion!(LocalProcessInfo);
|
||||
|
||||
impl LocalProcessInfo {
|
||||
fn flatten_to_exe_names(&self) -> HashSet<String> {
|
||||
let mut names = HashSet::new();
|
||||
|
||||
fn flatten(item: &LocalProcessInfo, names: &mut HashSet<String>) {
|
||||
if let Some(exe) = item.executable.file_name() {
|
||||
names.insert(exe.to_string_lossy().into_owned());
|
||||
}
|
||||
for proc in item.children.values() {
|
||||
flatten(proc, names);
|
||||
}
|
||||
}
|
||||
|
||||
flatten(self, &mut names);
|
||||
names
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
|
||||
impl LocalProcessInfo {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LocalPane {
|
||||
fn drop(&mut self) {
|
||||
// Avoid lingering zombies if we can, but don't block forever.
|
||||
|
108
mux/src/procinfo.rs
Normal file
108
mux/src/procinfo.rs
Normal file
@ -0,0 +1,108 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
|
||||
pub enum LocalProcessStatus {
|
||||
Idle,
|
||||
Run,
|
||||
Sleep,
|
||||
Stop,
|
||||
Zombie,
|
||||
Tracing,
|
||||
Dead,
|
||||
Wakekill,
|
||||
Waking,
|
||||
Parked,
|
||||
LockBlocked,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct LocalProcessInfo {
|
||||
pub pid: u32,
|
||||
pub ppid: u32,
|
||||
pub name: String,
|
||||
pub executable: PathBuf,
|
||||
pub argv: Vec<String>,
|
||||
pub cwd: PathBuf,
|
||||
pub status: LocalProcessStatus,
|
||||
pub children: HashMap<u32, LocalProcessInfo>,
|
||||
pub start_time: u64,
|
||||
}
|
||||
luahelper::impl_lua_conversion!(LocalProcessInfo);
|
||||
|
||||
impl LocalProcessInfo {
|
||||
pub fn flatten_to_exe_names(&self) -> HashSet<String> {
|
||||
let mut names = HashSet::new();
|
||||
|
||||
fn flatten(item: &LocalProcessInfo, names: &mut HashSet<String>) {
|
||||
if let Some(exe) = item.executable.file_name() {
|
||||
names.insert(exe.to_string_lossy().into_owned());
|
||||
}
|
||||
for proc in item.children.values() {
|
||||
flatten(proc, names);
|
||||
}
|
||||
}
|
||||
|
||||
flatten(self, &mut names);
|
||||
names
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
|
||||
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))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user