From d044155d4d24725fe2c1fe1d9d1c2b4e24aeb8ad Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Wed, 20 May 2026 14:08:24 +0000 Subject: [PATCH] Fix goroutine leak on context cancellation in ContainerExec Cancel the exec context when the caller's context is done so the ExecStartAndAttach goroutine terminates instead of running indefinitely. Assisted-by: Claude Opus 4.6 (1M context) --- internal/podman/client.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/podman/client.go b/internal/podman/client.go index 29d30e2..41c4fcd 100644 --- a/internal/podman/client.go +++ b/internal/podman/client.go @@ -302,13 +302,17 @@ func (c *Client) ContainerExec(ctx context.Context, name string, cmd []string) ( WithAttachOutput(true). WithAttachError(true) + execCtx, execCancel := context.WithCancel(c.conn) + defer execCancel() + execErr := make(chan error, 1) go func() { - execErr <- containers.ExecStartAndAttach(c.conn, sessionID, startOptions) + execErr <- containers.ExecStartAndAttach(execCtx, sessionID, startOptions) }() select { case <-ctx.Done(): + execCancel() return "", fmt.Errorf("executing command: %w", ctx.Err()) case err := <-execErr: if err != nil { @@ -350,13 +354,17 @@ func (c *Client) ContainerExecQuiet(ctx context.Context, name string, cmd []stri WithAttachOutput(true). WithAttachError(true) + execCtx, execCancel := context.WithCancel(c.conn) + defer execCancel() + execErr := make(chan error, 1) go func() { - execErr <- containers.ExecStartAndAttach(c.conn, sessionID, startOptions) + execErr <- containers.ExecStartAndAttach(execCtx, sessionID, startOptions) }() select { case <-ctx.Done(): + execCancel() return fmt.Errorf("executing command: %w", ctx.Err()) case err := <-execErr: if err != nil {