deb: retry the interrupt chroot removal while children die off
dpkg defers SIGINT until it reaches a safe state, so it can still be writing into the chroot when the watchdog's rm -rf starts racing through it, failing with "directory not empty" and leaving the tree half-removed. Retry the removal for a few seconds while the interrupted children finish dying off; a genuinely stuck tree still ends in the pkh prune message.
This commit is contained in:
+26
-9
@@ -60,31 +60,48 @@ fn sigint_cleanup_chroot(chroot_path: &Path) {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the chroot tree itself (tolerates a missing directory)
|
||||
let status = privileged_command("rm", is_root)
|
||||
.arg("-rf")
|
||||
.arg(chroot_path)
|
||||
.status();
|
||||
match status {
|
||||
Ok(status) if status.success() => {
|
||||
// Remove the chroot tree itself (tolerates a missing directory). A
|
||||
// child the Ctrl+C interrupted may still be finishing its writeout —
|
||||
// dpkg defers SIGINT until it reaches a safe state — so retry while rm
|
||||
// reports the tree non-empty instead of leaving it half-removed.
|
||||
const RETRIES: usize = 10;
|
||||
const RETRY_DELAY: std::time::Duration = std::time::Duration::from_millis(300);
|
||||
let mut last = None;
|
||||
for attempt in 0..=RETRIES {
|
||||
if attempt > 0 {
|
||||
std::thread::sleep(RETRY_DELAY);
|
||||
}
|
||||
last = Some(
|
||||
privileged_command("rm", is_root)
|
||||
.arg("-rf")
|
||||
.arg(chroot_path)
|
||||
.status(),
|
||||
);
|
||||
if matches!(&last, Some(Ok(status)) if status.success()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
match last {
|
||||
Some(Ok(status)) if status.success() => {
|
||||
log::debug!(
|
||||
"Removed chroot {} during interrupt cleanup",
|
||||
chroot_path.display()
|
||||
);
|
||||
}
|
||||
Ok(status) => {
|
||||
Some(Ok(status)) => {
|
||||
log::error!(
|
||||
"Failed to remove chroot {} during interrupt cleanup \
|
||||
(rm exited with {status}); run `pkh prune`",
|
||||
chroot_path.display()
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
Some(Err(e)) => {
|
||||
log::error!(
|
||||
"Failed to run rm for chroot {} during interrupt cleanup: {e}; run `pkh prune`",
|
||||
chroot_path.display()
|
||||
);
|
||||
}
|
||||
None => unreachable!("at least one rm attempt ran"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user