use proc_connector::{NetlinkMessageIter, ProcConnector, ProcEvent as PcEvent};
pub use proc_tree::{
CacheStore, DefaultCache, DefaultTree, PidNode, ProcEvent, ProcInfo, ProcessLink, TreeStore,
read_proc_start_time_ns,
};
pub const PROC_CACHE_CAP: u64 = 65536;
pub const PROC_CACHE_TTL_SECS: u64 = 600;
pub const PID_TREE_CAP: u64 = 65536;
pub const PID_TREE_TTL_SECS: u64 = 600;
pub fn try_create_connector() -> Option<ProcConnector> {
let conn = match ProcConnector::new() {
Ok(c) => c,
Err(e) => {
eprintln!(
"[WARNING] Failed to create proc connector: {e}. \
Process tree tracking will be unavailable."
);
return None;
}
};
if let Err(e) = conn.set_nonblocking() {
eprintln!("[WARNING] Failed to set proc connector non-blocking: {e}");
return None;
}
Some(conn)
}
pub fn handle_proc_events(cache: &DefaultCache, tree: &DefaultTree, data: &[u8], n: usize) {
let mut events: Vec<ProcEvent> = Vec::new();
for msg in NetlinkMessageIter::new(data, n) {
match msg {
Ok(Some(PcEvent::Exec {
pid, timestamp_ns, ..
})) => {
events.push(ProcEvent::Exec { pid, timestamp_ns });
}
Ok(Some(PcEvent::Fork {
child_pid,
parent_pid,
timestamp_ns,
..
})) => {
events.push(ProcEvent::Fork {
child_pid,
parent_pid,
timestamp_ns,
});
}
Ok(Some(PcEvent::Exit { pid, .. })) => {
events.push(ProcEvent::Exit { pid });
}
Ok(Some(_)) => {}
Ok(None) => {}
Err(proc_connector::Error::Overrun) => {
eprintln!("[WARNING] proc connector overrun — some events may have been lost");
}
Err(proc_connector::Error::Truncated) => {
eprintln!("[WARNING] proc connector truncated message, continuing...");
}
Err(e) => {
eprintln!("proc connector parse error: {e}");
}
}
}
if !events.is_empty() {
proc_tree::handle_events(tree, cache, &events);
}
}