mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-03 03:15:43 +00:00
sys: change PidStat API
Rather than standalone functions, `PidStat` now provides a `read_for_pid` and `parse` method. Both are public. One side effect is that the documentation of PidStat's contents are on the same page as the ways to retrieve it. Additionally, we deprecate `read_proc_starttime` as it was reading the entire contents to then filter out one value, in order to promote caching. The standalone `read_proc_pid_stat` method is now also deprecated. Once we add pid-fds the API will feel cleaner this way. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
e3b41dc815
commit
42a155668e
@ -26,6 +26,7 @@ lazy_static! {
|
||||
static ref CLOCK_TICKS: f64 = sysconf(libc::_SC_CLK_TCK) as f64;
|
||||
}
|
||||
|
||||
/// Selected contents of the `/proc/PID/stat` file.
|
||||
pub struct PidStat {
|
||||
pub pid: Pid,
|
||||
pub ppid: Pid,
|
||||
@ -38,12 +39,14 @@ pub struct PidStat {
|
||||
pub rss: i64,
|
||||
}
|
||||
|
||||
pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<PidStat, Error> {
|
||||
let stat = parse_proc_pid_stat(std::str::from_utf8(&std::fs::read(format!(
|
||||
impl PidStat {
|
||||
/// Retrieve the `stat` file contents of a process.
|
||||
pub fn read_for_pid(pid: Pid) -> Result<Self, Error> {
|
||||
let stat = Self::parse(std::str::from_utf8(&std::fs::read(format!(
|
||||
"/proc/{}/stat",
|
||||
pid
|
||||
))?)?)?;
|
||||
if stat.pid.as_raw() != pid {
|
||||
if stat.pid != pid {
|
||||
bail!(
|
||||
"unexpected pid for process: found pid {} in /proc/{}/stat",
|
||||
stat.pid.as_raw(),
|
||||
@ -51,9 +54,10 @@ pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<PidStat, Error> {
|
||||
);
|
||||
}
|
||||
Ok(stat)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_proc_pid_stat(statstr: &str) -> Result<PidStat, Error> {
|
||||
/// Parse the contents of a `/proc/PID/stat` file.
|
||||
pub fn parse(statstr: &str) -> Result<PidStat, Error> {
|
||||
// It starts with the pid followed by a '('.
|
||||
let cmdbeg = statstr
|
||||
.find('(')
|
||||
@ -111,11 +115,18 @@ fn parse_proc_pid_stat(statstr: &str) -> Result<PidStat, Error> {
|
||||
// and more...
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read `/proc/PID/stat` for a pid.
|
||||
#[deprecated(note = "use `PidStat::read_for_pid`")]
|
||||
pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<PidStat, Error> {
|
||||
PidStat::read_for_pid(Pid::from_raw(pid))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_proc_pid_stat() {
|
||||
let stat = parse_proc_pid_stat(
|
||||
let stat = PidStat::parse(
|
||||
"28900 (zsh) S 22489 28900 28900 34826 10252 4194304 6851 5946551 0 2344 6 3 25205 1413 \
|
||||
20 0 1 0 287592 12496896 1910 18446744073709551615 93999319244800 93999319938061 \
|
||||
140722897984224 0 0 0 2 3686404 134295555 1 0 0 17 10 0 0 0 0 0 93999320079088 \
|
||||
@ -134,19 +145,15 @@ fn test_read_proc_pid_stat() {
|
||||
assert_eq!(stat.rss, 1910 * 4096);
|
||||
}
|
||||
|
||||
#[deprecated(note = "use `PidStat`")]
|
||||
pub fn read_proc_starttime(pid: libc::pid_t) -> Result<u64, Error> {
|
||||
let info = read_proc_pid_stat(pid)?;
|
||||
|
||||
Ok(info.starttime)
|
||||
PidStat::read_for_pid(Pid::from_raw(pid)).map(|stat| stat.starttime)
|
||||
}
|
||||
|
||||
pub fn check_process_running(pid: libc::pid_t) -> Option<PidStat> {
|
||||
if let Ok(info) = read_proc_pid_stat(pid) {
|
||||
if info.status != b'Z' {
|
||||
return Some(info);
|
||||
}
|
||||
}
|
||||
None
|
||||
PidStat::read_for_pid(Pid::from_raw(pid))
|
||||
.ok()
|
||||
.filter(|stat| stat.status != b'Z')
|
||||
}
|
||||
|
||||
pub fn check_process_running_pstart(pid: libc::pid_t, pstart: u64) -> Option<PidStat> {
|
||||
|
Loading…
Reference in New Issue
Block a user