Skip to content

Commit 902bfc1

Browse files
G4614claude
andcommitted
test(recovery): reap detached tree in live_process/dead_process too
Repeated/root verification of the prior fix surfaced two more recovery tests that leak the same detached inner tree (2 procs each, every run): - recovery_with_live_process cleans up via production remove(force=true), which only signals the recorded outer bwrap; - recovery_with_dead_process manually SIGKILLs the recorded outer bwrap. Both leave the inner pid-ns bwrap + shim + VM alive (post-#851). Arm a ShimReaper (pkill -9 -f <box id>) in both, matching the two pid-file tests, so each reaps its whole tree on drop. Verified as root, repeated: pid-file tests x10 -> 0 leak; full recovery suite x3 -> 9 pass, 0 leak each. Compiles (--features krun,gvproxy); cargo fmt clean. The underlying production leak (stop / rm -f only signal the outer bwrap, so a detached box's inner tree survives; cgroup.kill reaps it) is a separate runtime-side bug, handled in its own draft PR — this commit only keeps the recovery suite from leaking. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 043f04f commit 902bfc1

1 file changed

Lines changed: 8 additions & 0 deletions

File tree

src/boxlite/tests/recovery.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ async fn recovery_with_live_process() {
5656
let home = boxlite_test_utils::home::PerTestBoxHome::new();
5757
let box_id: String;
5858
let original_pid: u32;
59+
// Detached box: the teardown `remove(force)` only signals the recorded
60+
// outer bwrap, leaving the inner pid-ns tree alive (see ShimReaper).
61+
let mut reaper = ShimReaper(None);
5962

6063
// Create box with detach=true
6164
{
@@ -78,6 +81,7 @@ async fn recovery_with_live_process() {
7881

7982
let _ = handle.exec(BoxCommand::new("sleep").args(["300"])).await;
8083
box_id = handle.id().to_string();
84+
reaper.0 = Some(box_id.clone());
8185

8286
let pf = pid_file_path(&home.path, &box_id);
8387
original_pid = PidFileReader::at(&pf).read().map(|r| r.pid).unwrap();
@@ -109,6 +113,9 @@ async fn recovery_with_live_process() {
109113
async fn recovery_with_dead_process() {
110114
let home = boxlite_test_utils::home::PerTestBoxHome::new();
111115
let box_id: String;
116+
// Detached box: SIGKILLing the recorded outer bwrap below leaves the inner
117+
// pid-ns tree alive; the reaper kills it by id on drop (see ShimReaper).
118+
let mut reaper = ShimReaper(None);
112119

113120
// Create box
114121
{
@@ -131,6 +138,7 @@ async fn recovery_with_dead_process() {
131138

132139
let _ = handle.exec(BoxCommand::new("sleep").args(["300"])).await;
133140
box_id = handle.id().to_string();
141+
reaper.0 = Some(box_id.clone());
134142

135143
let pf = pid_file_path(&home.path, &box_id);
136144
let original_pid = PidFileReader::at(&pf).read().map(|r| r.pid).unwrap();

0 commit comments

Comments
 (0)