mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-04 07:23:34 +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;
|
static ref CLOCK_TICKS: f64 = sysconf(libc::_SC_CLK_TCK) as f64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Selected contents of the `/proc/PID/stat` file.
|
||||||
pub struct PidStat {
|
pub struct PidStat {
|
||||||
pub pid: Pid,
|
pub pid: Pid,
|
||||||
pub ppid: Pid,
|
pub ppid: Pid,
|
||||||
@ -38,12 +39,14 @@ pub struct PidStat {
|
|||||||
pub rss: i64,
|
pub rss: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<PidStat, Error> {
|
impl PidStat {
|
||||||
let stat = parse_proc_pid_stat(std::str::from_utf8(&std::fs::read(format!(
|
/// 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",
|
"/proc/{}/stat",
|
||||||
pid
|
pid
|
||||||
))?)?)?;
|
))?)?)?;
|
||||||
if stat.pid.as_raw() != pid {
|
if stat.pid != pid {
|
||||||
bail!(
|
bail!(
|
||||||
"unexpected pid for process: found pid {} in /proc/{}/stat",
|
"unexpected pid for process: found pid {} in /proc/{}/stat",
|
||||||
stat.pid.as_raw(),
|
stat.pid.as_raw(),
|
||||||
@ -51,9 +54,10 @@ pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<PidStat, Error> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(stat)
|
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 '('.
|
// It starts with the pid followed by a '('.
|
||||||
let cmdbeg = statstr
|
let cmdbeg = statstr
|
||||||
.find('(')
|
.find('(')
|
||||||
@ -111,11 +115,18 @@ fn parse_proc_pid_stat(statstr: &str) -> Result<PidStat, Error> {
|
|||||||
// and more...
|
// and more...
|
||||||
|
|
||||||
Ok(out)
|
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]
|
#[test]
|
||||||
fn test_read_proc_pid_stat() {
|
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 \
|
"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 \
|
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 \
|
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);
|
assert_eq!(stat.rss, 1910 * 4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(note = "use `PidStat`")]
|
||||||
pub fn read_proc_starttime(pid: libc::pid_t) -> Result<u64, Error> {
|
pub fn read_proc_starttime(pid: libc::pid_t) -> Result<u64, Error> {
|
||||||
let info = read_proc_pid_stat(pid)?;
|
PidStat::read_for_pid(Pid::from_raw(pid)).map(|stat| stat.starttime)
|
||||||
|
|
||||||
Ok(info.starttime)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_process_running(pid: libc::pid_t) -> Option<PidStat> {
|
pub fn check_process_running(pid: libc::pid_t) -> Option<PidStat> {
|
||||||
if let Ok(info) = read_proc_pid_stat(pid) {
|
PidStat::read_for_pid(Pid::from_raw(pid))
|
||||||
if info.status != b'Z' {
|
.ok()
|
||||||
return Some(info);
|
.filter(|stat| stat.status != b'Z')
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_process_running_pstart(pid: libc::pid_t, pstart: u64) -> Option<PidStat> {
|
pub fn check_process_running_pstart(pid: libc::pid_t, pstart: u64) -> Option<PidStat> {
|
||||||
|
Loading…
Reference in New Issue
Block a user