use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CleanupExpectation {
Strong,
BestEffort { sweep_budget_ms: u64 },
}
impl CleanupExpectation {
pub fn for_current_tier(tier_label: Option<&str>) -> Self {
#[cfg(target_os = "windows")]
{
let _ = tier_label;
CleanupExpectation::Strong
}
#[cfg(target_os = "linux")]
{
match tier_label {
Some("full") => CleanupExpectation::Strong,
_ => CleanupExpectation::BestEffort {
sweep_budget_ms: 2000,
},
}
}
#[cfg(target_os = "macos")]
{
let _ = tier_label;
CleanupExpectation::BestEffort {
sweep_budget_ms: 2000,
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
{
let _ = tier_label;
CleanupExpectation::BestEffort {
sweep_budget_ms: 2000,
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KillOutcome {
Exited,
KilledOnDeadline,
}
pub fn kill_on_deadline(
handle: &mut crate::sandbox::SandboxHandle,
deadline: Instant,
poll: Duration,
) -> (KillOutcome, i32) {
loop {
if let Some(code) = handle.try_wait() {
return (KillOutcome::Exited, code);
}
if Instant::now() >= deadline {
handle.terminate();
let end = Instant::now() + Duration::from_secs(10);
loop {
if let Some(code) = handle.try_wait() {
return (KillOutcome::KilledOnDeadline, code);
}
if Instant::now() >= end {
handle.terminate();
return (KillOutcome::KilledOnDeadline, -1);
}
std::thread::sleep(poll);
}
}
std::thread::sleep(poll);
}
}
#[cfg(test)]
mod killer_tests {
use super::*;
#[test]
fn expectation_matrix() {
#[cfg(target_os = "linux")]
{
assert_eq!(
CleanupExpectation::for_current_tier(Some("full")),
CleanupExpectation::Strong
);
assert!(matches!(
CleanupExpectation::for_current_tier(Some("fs-only")),
CleanupExpectation::BestEffort { .. }
));
}
#[cfg(target_os = "windows")]
{
assert_eq!(
CleanupExpectation::for_current_tier(None),
CleanupExpectation::Strong
);
}
#[cfg(target_os = "macos")]
{
assert!(matches!(
CleanupExpectation::for_current_tier(None),
CleanupExpectation::BestEffort { .. }
));
}
}
}