From fcdc42707d1b901cdaf129c6144755a35666154a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 4 Nov 2023 22:53:48 +0100 Subject: [PATCH] Greatly reduce needed memory when retrieving process arguments and environment --- src/unix/apple/macos/process.rs | 32 ++++++++++++++++------ src/unix/apple/system.rs | 47 ++------------------------------- 2 files changed, 26 insertions(+), 53 deletions(-) diff --git a/src/unix/apple/macos/process.rs b/src/unix/apple/macos/process.rs index d549d4ee3..4112586be 100644 --- a/src/unix/apple/macos/process.rs +++ b/src/unix/apple/macos/process.rs @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf}; use std::borrow::Borrow; -use libc::{c_int, c_void, kill, size_t}; +use libc::{c_int, c_void, kill}; use crate::{DiskUsage, Gid, Pid, Process, ProcessRefreshKind, ProcessStatus, Signal, Uid}; @@ -363,7 +363,6 @@ unsafe fn convert_node_path_info(node: &libc::vnode_info_path) -> PathBuf { unsafe fn create_new_process( pid: Pid, - mut arg_max: size_t, now: u64, refresh_kind: ProcessRefreshKind, info: Option, @@ -417,8 +416,6 @@ unsafe fn create_new_process( p => Some(Pid(p)), }; - let mut proc_args: Vec = Vec::with_capacity(arg_max as _); - let mut mib = [libc::CTL_KERN, libc::KERN_PROCARGS2, pid.0 as _]; /* * /---------------\ 0x00000000 * | ::::::::::::: | @@ -449,6 +446,26 @@ unsafe fn create_new_process( * : : * \---------------/ 0xffffffff */ + let mut mib = [libc::CTL_KERN, libc::KERN_PROCARGS2, pid.0 as _]; + let mut arg_max = 0; + // First we retrieve the size we will need for our data (in `arg_max`). + if libc::sysctl( + mib.as_mut_ptr(), + mib.len() as _, + std::ptr::null_mut(), + &mut arg_max, + std::ptr::null_mut(), + 0, + ) == -1 + { + sysinfo_debug!( + "couldn't get arguments and environment size for PID {}", + pid.0 + ); + return Err(()); // not enough rights I assume? + } + + let mut proc_args: Vec = Vec::with_capacity(arg_max as _); if libc::sysctl( mib.as_mut_ptr(), mib.len() as _, @@ -459,7 +476,7 @@ unsafe fn create_new_process( ) == -1 { sysinfo_debug!("couldn't get arguments and environment for PID {}", pid.0); - return Err(()); // not enough rights I assume? + return Err(()); // What changed since the previous call? Dark magic! } proc_args.set_len(arg_max); @@ -577,7 +594,6 @@ fn get_environ(mut data: &[u8]) -> Vec { pub(crate) fn update_process( wrap: &Wrap, pid: Pid, - size: size_t, time_interval: Option, now: u64, refresh_kind: ProcessRefreshKind, @@ -600,7 +616,7 @@ pub(crate) fn update_process( // We don't it to be removed, just replaced. p.updated = true; // The owner of this PID changed. - return create_new_process(pid, size, now, refresh_kind, Some(info)); + return create_new_process(pid, now, refresh_kind, Some(info)); } } let task_info = get_task_info(pid); @@ -640,7 +656,7 @@ pub(crate) fn update_process( p.updated = true; return Ok(None); } - create_new_process(pid, size, now, refresh_kind, get_bsd_info(pid)) + create_new_process(pid, now, refresh_kind, get_bsd_info(pid)) } } diff --git a/src/unix/apple/system.rs b/src/unix/apple/system.rs index c89b4c642..0a48dfd14 100644 --- a/src/unix/apple/system.rs +++ b/src/unix/apple/system.rs @@ -13,9 +13,6 @@ use std::mem; #[cfg(all(target_os = "macos", not(feature = "apple-sandbox")))] use std::time::SystemTime; -#[cfg(all(target_os = "macos", not(feature = "apple-sandbox")))] -use libc::size_t; - use libc::{ c_int, c_void, host_statistics64, mach_port_t, sysconf, sysctl, timeval, vm_statistics64, _SC_PAGESIZE, @@ -182,7 +179,6 @@ impl SystemInner { } if let Some(pids) = get_proc_list() { let now = get_now(); - let arg_max = get_arg_max(); let port = self.port; let time_interval = self.clock_info.as_mut().map(|c| c.get_time_interval(port)); let entries: Vec = { @@ -193,15 +189,7 @@ impl SystemInner { into_iter(pids) .flat_map(|pid| { - match update_process( - wrap, - pid, - arg_max as size_t, - time_interval, - now, - refresh_kind, - false, - ) { + match update_process(wrap, pid, time_interval, now, refresh_kind, false) { Ok(x) => x, _ => None, } @@ -232,7 +220,6 @@ impl SystemInner { refresh_kind: ProcessRefreshKind, ) -> bool { let mut time_interval = None; - let arg_max = get_arg_max(); let now = get_now(); if refresh_kind.cpu() { @@ -241,15 +228,7 @@ impl SystemInner { } match { let wrap = Wrap(UnsafeCell::new(&mut self.process_list)); - update_process( - &wrap, - pid, - arg_max as size_t, - time_interval, - now, - refresh_kind, - true, - ) + update_process(&wrap, pid, time_interval, now, refresh_kind, true) } { Ok(Some(p)) => { self.process_list.insert(p.pid(), p); @@ -430,28 +409,6 @@ impl SystemInner { } } -#[cfg(all(target_os = "macos", not(feature = "apple-sandbox")))] -fn get_arg_max() -> usize { - let mut mib = [libc::CTL_KERN, libc::KERN_ARGMAX]; - let mut arg_max = 0i32; - let mut size = mem::size_of::(); - unsafe { - if sysctl( - mib.as_mut_ptr(), - mib.len() as _, - (&mut arg_max) as *mut i32 as *mut c_void, - &mut size, - std::ptr::null_mut(), - 0, - ) == -1 - { - 4096 // We default to this value - } else { - arg_max as usize - } - } -} - fn get_system_info(value: c_int, default: Option<&str>) -> Option { let mut mib: [c_int; 2] = [libc::CTL_KERN, value]; let mut size = 0;