use super::{check_liveness, container_dir, read_state, ContainerStatus};
pub fn cmd_rm(name: &str, force: bool) -> Result<(), Box<dyn std::error::Error>> {
let state = read_state(name).map_err(|_| format!("no container named '{}'", name))?;
if state.status == ContainerStatus::Running && check_liveness(state.pid) {
if force {
let r = unsafe { libc::kill(state.pid, libc::SIGTERM) };
if r != 0 {
let err = std::io::Error::last_os_error();
if err.raw_os_error() != Some(libc::ESRCH) {
return Err(format!("kill({}): {}", state.pid, err).into());
}
}
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
while check_liveness(state.pid) && std::time::Instant::now() < deadline {
std::thread::sleep(std::time::Duration::from_millis(100));
}
if check_liveness(state.pid) {
unsafe { libc::kill(state.pid, libc::SIGKILL) };
for _ in 0..10 {
std::thread::sleep(std::time::Duration::from_millis(100));
if !check_liveness(state.pid) {
break;
}
}
}
if state.watcher_pid > 0 {
let watcher_deadline =
std::time::Instant::now() + std::time::Duration::from_secs(5);
while check_liveness(state.watcher_pid as i32)
&& std::time::Instant::now() < watcher_deadline
{
std::thread::sleep(std::time::Duration::from_millis(50));
}
}
} else {
return Err(format!(
"container '{}' is running; use --force to remove it or `pelagos stop {}` first",
name, name
)
.into());
}
}
let dir = container_dir(name);
std::fs::remove_dir_all(&dir).map_err(|e| format!("remove {}: {}", dir.display(), e))?;
Ok(())
}