From 0d07366b958f0a561aab153c670354ab63feb318 Mon Sep 17 00:00:00 2001 From: Yashika0724 Date: Sun, 7 Jun 2026 16:14:21 +0530 Subject: [PATCH] fix(delete): handle already-exited processes during force-delete A force-delete can race with a guest shutdown or a previous kill attempt, leaving the VMM process already exited by the time killProcess() runs. In that case syscall.Kill(pid, SIGKILL) returns ESRCH, which currently propagates as an error even though the process is no longer running, causing the force-delete to abort before cleaning up the container's runtime state. Treat ESRCH from the initial SIGKILL as a successful outcome, and continue with Delete() even if Kill() returns an error, since the purpose of --force is to reclaim runtime state regardless of whether the target process is still around. Signed-off-by: Yashika0724 --- cmd/urunc/delete.go | 11 ++++++++--- pkg/unikontainers/hypervisors/utils.go | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cmd/urunc/delete.go b/cmd/urunc/delete.go index 41eeeac69..706129c4e 100644 --- a/cmd/urunc/delete.go +++ b/cmd/urunc/delete.go @@ -74,9 +74,14 @@ status of "ubuntu01" as "stopped" the following will delete resources held for return err } if cmd.Bool("force") { - err := unikontainer.Kill() - if err != nil { - return err + // Forcing a delete must remain idempotent even if the + // container's process has already exited (e.g. it was + // killed by a previous attempt or exited on its own). + // Log any kill error but still proceed to clean up the + // container's resources, otherwise a stale state would + // make every subsequent delete attempt fail the same way. + if err := unikontainer.Kill(); err != nil { + logrus.WithError(err).Error("failed to kill container during forced delete") } } err = unikontainer.Delete() diff --git a/pkg/unikontainers/hypervisors/utils.go b/pkg/unikontainers/hypervisors/utils.go index 6694c6ebe..6470b6df9 100644 --- a/pkg/unikontainers/hypervisors/utils.go +++ b/pkg/unikontainers/hypervisors/utils.go @@ -71,6 +71,10 @@ func killProcess(pid int) error { const timeout = 2 * time.Second err := syscall.Kill(pid, unix.SIGKILL) if err != nil { + if errors.Is(err, syscall.ESRCH) { + // process is already dead + return nil + } return err } deadline := time.Now().Add(timeout)