stackless_core/
process.rs1use sysinfo::{Pid, ProcessRefreshKind, ProcessesToUpdate, System};
5
6use crate::types::{Pid as StacklessPid, ProcessStartTime};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct ProcessStamp {
11 pub pid: StacklessPid,
12 pub start_time: ProcessStartTime,
14}
15
16impl ProcessStamp {
17 pub fn current() -> Self {
19 let pid = StacklessPid::from_os(std::process::id());
20 Self {
21 pid,
22 start_time: start_time_of(pid).unwrap_or(ProcessStartTime::from_os(0)),
23 }
24 }
25
26 pub fn of(pid: u32) -> Option<Self> {
28 let pid = StacklessPid::from_os(pid);
29 start_time_of(pid).map(|start_time| Self { pid, start_time })
30 }
31
32 pub fn is_alive(&self) -> bool {
35 start_time_of(self.pid).is_some_and(|start| start == self.start_time)
36 }
37}
38
39fn start_time_of(pid: StacklessPid) -> Option<ProcessStartTime> {
40 let raw = pid.get();
41 let mut system = System::new();
42 system.refresh_processes_specifics(
43 ProcessesToUpdate::Some(&[Pid::from_u32(raw)]),
44 false,
45 ProcessRefreshKind::nothing(),
46 );
47 system
48 .process(Pid::from_u32(raw))
49 .map(sysinfo::Process::start_time)
50 .map(ProcessStartTime::from_os)
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn current_process_is_alive() {
59 let stamp = ProcessStamp::current();
60 assert!(stamp.start_time.get() > 0);
61 assert!(stamp.is_alive());
62 }
63
64 #[test]
65 fn wrong_start_time_is_not_alive() {
66 let stamp = ProcessStamp {
67 pid: StacklessPid::from_os(std::process::id()),
68 start_time: ProcessStartTime::from_os(1),
69 };
70 assert!(!stamp.is_alive());
71 }
72
73 #[test]
74 fn bogus_pid_is_not_alive() {
75 let stamp = ProcessStamp {
76 pid: StacklessPid::from_os(u32::MAX - 1),
77 start_time: ProcessStartTime::from_os(1),
78 };
79 assert!(!stamp.is_alive());
80 }
81}