AI-Studio/runtime/src/stale_process_cleanup.rs

90 lines
3.3 KiB
Rust
Raw Normal View History

use std::fs;
use std::fs::File;
use std::io::{Error, ErrorKind, Write};
use std::path::{PathBuf};
use log::{info, warn};
use sysinfo::{Pid, ProcessesToUpdate, Signal, System};
use crate::sidecar_types::SidecarType;
fn parse_pid_file(content: &str) -> Result<(u32, String), Error> {
let mut lines = content
.lines()
.map(|line| line.trim())
.filter(|line| !line.is_empty());
let pid_str = lines
.next()
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "Missing PID in file"))?;
let pid: u32 = pid_str
.parse()
.map_err(|_| Error::new(ErrorKind::InvalidData, "Invalid PID in file"))?;
let name = lines
.next()
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "Missing process name in file"))?
.to_string();
Ok((pid, name))
}
pub fn kill_stale_process(pid_file_path: PathBuf, sidecar_type: SidecarType) -> Result<(), Error> {
if !pid_file_path.exists() {
return Ok(());
}
let pid_file_content = fs::read_to_string(&pid_file_path)?;
let (pid, expected_name) = parse_pid_file(&pid_file_content)?;
let mut system = System::new_all();
let pid = Pid::from_u32(pid);
system.refresh_processes(ProcessesToUpdate::Some(&[pid]), true);
if let Some(process) = system.process(pid){
let name = process.name().to_string_lossy();
if name != expected_name {
return Err(Error::new(
ErrorKind::InvalidInput,
format!(
"Process name does not match: expected '{}' but found '{}'",
expected_name, name
),
));
}
let killed = process.kill_with(Signal::Kill).unwrap_or_else(|| process.kill());
if !killed {
return Err(Error::new(ErrorKind::Other, "Failed to kill process"));
}
info!(Source="Stale Process Cleanup";"{}: Killed process: \"{}\"", sidecar_type,pid_file_path.display());
} else {
info!(Source="Stale Process Cleanup";"{}: Pid file with process number '{}' was found, but process was not.", sidecar_type, pid);
};
fs::remove_file(&pid_file_path)?;
info!(Source="Stale Process Cleanup";"{}: Deleted redundant Pid file: \"{}\"", sidecar_type,pid_file_path.display());
Ok(())
}
pub fn log_potential_stale_process(pid_file_path: PathBuf, pid: u32, sidecar_type: SidecarType) {
let mut system = System::new_all();
let pid = Pid::from_u32(pid);
system.refresh_processes(ProcessesToUpdate::Some(&[pid]), true);
let Some(process) = system.process(pid) else {
warn!(Source="Stale Process Cleanup";
"{}: Pid file with process number '{}' was not created because the process was not found.",
sidecar_type, pid
);
return;
};
match File::create(&pid_file_path) {
Ok(mut file) => {
let name = process.name().to_string_lossy();
let content = format!("{pid}\n{name}\n");
if let Err(e) = file.write_all(content.as_bytes()) {
warn!(Source="Stale Process Cleanup";"{}: Failed to write to \"{}\": {}", sidecar_type,pid_file_path.display(), e);
}
}
Err(e) => {
warn!(Source="Stale Process Cleanup";"{}: Failed to create \"{}\": {}", sidecar_type, pid_file_path.display(), e);
}
}
}