From e77acc475bd21ec1093b33a3d278a34b567c5c22 Mon Sep 17 00:00:00 2001 From: Teresaliu Date: Fri, 18 Jul 2025 05:04:17 -0400 Subject: [PATCH] Add cleanup IO process after nerdctl stop --- .../container/container_stop_linux_test.go | 29 +++++++++++++++++++ pkg/containerutil/containerutil.go | 10 +++++++ 2 files changed, 39 insertions(+) diff --git a/cmd/nerdctl/container/container_stop_linux_test.go b/cmd/nerdctl/container/container_stop_linux_test.go index 135da90a938..647fc76a21a 100644 --- a/cmd/nerdctl/container/container_stop_linux_test.go +++ b/cmd/nerdctl/container/container_stop_linux_test.go @@ -19,6 +19,7 @@ package container import ( "fmt" "io" + "os" "strings" "testing" "time" @@ -199,3 +200,31 @@ func TestStopWithTimeout(t *testing.T) { // The container should get the SIGKILL before the 10s default timeout assert.Assert(t, elapsed < 10*time.Second, "Container did not respect --timeout flag") } + +func TestStopCleanupFIFOs(t *testing.T) { + t.Parallel() + + base := testutil.NewBase(t) + testContainerName := testutil.Identifier(t) + + // Stop the container after 2 seconds + go func() { + time.Sleep(2 * time.Second) + base.Cmd("stop", testContainerName).AssertOK() + }() + + // Start a container that is automatically removed after it exits + base.Cmd("run", "--rm", "--name", testContainerName, testutil.NginxAlpineImage).AssertOK() + + fifoDir := "/run/containerd/fifo" + entries, err := os.ReadDir(fifoDir) + assert.NilError(t, err, "failed to read fifo directory") + + if len(entries) != 0 { + for _, entry := range entries { + t.Logf("Leaked FIFO file: %s", entry.Name()) + } + } + // The FIFO directory should be empty after the container be stopped + assert.Assert(t, len(entries) == 0, "Expected no FIFO files under %s, but found %d", fifoDir, len(entries)) +} diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 0bebf2310ea..5dd824605e0 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -385,6 +385,16 @@ func Stop(ctx context.Context, container containerd.Container, timeout *time.Dur return err } + // Cleanup the IO after a successful Stop + io := task.IO() + if io != nil { + defer func() { + if cerr := io.Close(); cerr != nil { + log.G(ctx).Warnf("failed to close IO for container %s: %v", container.ID(), cerr) + } + }() + } + status, err := task.Status(ctx) if err != nil { return err