Skip to content

Commit a7b393b

Browse files
authored
Merge pull request #858 from Dstack-TEE/codex/fix-vmm-svstop-child-reaping
fix(vmm): reap VM launcher children on SvStop
2 parents 3b84f2a + 09fd2aa commit a7b393b

3 files changed

Lines changed: 27 additions & 3 deletions

File tree

dstack/supervisor/src/process.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ impl ProcessStateRT {
8383
pub(crate) fn is_started(&self) -> bool {
8484
self.started
8585
}
86+
87+
/// An explicit stop may arrive just after the process exited on its own
88+
/// (VM launchers exit cleanly after reaping their children). Report such
89+
/// a clean exit as the intended stop, but keep non-zero exit codes and
90+
/// errors visible for diagnostics. `stopped_at` recorded by the wait task
91+
/// is left untouched.
92+
fn normalize_clean_exit(&mut self) {
93+
if matches!(self.status, ProcessStatus::Exited(0)) {
94+
self.status = ProcessStatus::Stopped;
95+
}
96+
}
8697
}
8798

8899
impl ProcessStateRT {
@@ -289,8 +300,13 @@ impl Process {
289300
if is_running {
290301
bail!("Missing kill tx for process");
291302
}
303+
state.normalize_clean_exit();
292304
return Ok(());
293305
};
306+
if !is_running {
307+
state.normalize_clean_exit();
308+
return Ok(());
309+
}
294310
match stop_tx.send(()) {
295311
Ok(()) => Ok(()),
296312
Err(()) => match is_running {

dstack/vmm/src/app.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ impl App {
468468
Ok(())
469469
}
470470

471-
async fn stop_vm_process(&self, id: &str) -> Result<()> {
471+
pub(crate) async fn stop_vm_process(&self, id: &str) -> Result<()> {
472472
let Some(info) = self.supervisor.info(id).await? else {
473473
return Ok(());
474474
};

dstack/vmm/src/main_service.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,16 @@ impl VmmRpc for RpcHandler {
841841
}
842842

843843
async fn sv_stop(self, request: Id) -> Result<()> {
844-
self.app.supervisor.stop(&request.id).await?;
845-
Ok(())
844+
// VM launcher processes own QEMU and swtpm children. Route them through
845+
// the VM-aware stop path so the launcher can reap those children; the
846+
// same helper preserves generic Supervisor stop semantics for every
847+
// other process type.
848+
self.app
849+
.supervisor
850+
.info(&request.id)
851+
.await?
852+
.context("Supervisor process not found")?;
853+
self.app.stop_vm_process(&request.id).await
846854
}
847855

848856
async fn sv_remove(self, request: Id) -> Result<()> {

0 commit comments

Comments
 (0)