cmd, commit: register shutdown handler to unpause container

When --pause defaults to true, a Ctrl-C during commit would leave the
container paused.  Register a shutdown handler that unpauses the
container on SIGINT/SIGTERM so it is always restored to its running
state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2026-05-27 09:30:33 +00:00
parent db804fb1b9
commit 1c2a2ffe87
No known key found for this signature in database
GPG key ID: 67E38F7A8BA21772

View file

@ -6,6 +6,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"os"
"slices" "slices"
"strings" "strings"
@ -16,6 +17,7 @@ import (
"go.podman.io/image/v5/types" "go.podman.io/image/v5/types"
"go.podman.io/podman/v6/libpod/define" "go.podman.io/podman/v6/libpod/define"
"go.podman.io/podman/v6/libpod/events" "go.podman.io/podman/v6/libpod/events"
"go.podman.io/podman/v6/libpod/shutdown"
) )
// ContainerCommitOptions is a struct used to commit a container to an image // ContainerCommitOptions is a struct used to commit a container to an image
@ -49,10 +51,21 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
} }
if (c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStateStopping) && options.Pause { if (c.state.State == define.ContainerStateRunning || c.state.State == define.ContainerStateStopping) && options.Pause {
// The container lock is held, so no concurrent Commit can
// register a handler with the same name.
handlerName := fmt.Sprintf("commit-unpause-%s", c.ID())
if err := shutdown.Register(handlerName, func(sig os.Signal) error {
logrus.Debugf("Received %v, unpausing container %q", sig, c.ID())
return c.unpause()
}); err != nil && !errors.Is(err, shutdown.ErrHandlerExists) {
logrus.Errorf("Registering shutdown handler for container %q: %v", c.ID(), err)
}
if err := c.pause(); err != nil { if err := c.pause(); err != nil {
_ = shutdown.Unregister(handlerName)
return nil, fmt.Errorf("pausing container %q to commit: %w", c.ID(), err) return nil, fmt.Errorf("pausing container %q to commit: %w", c.ID(), err)
} }
defer func() { defer func() {
_ = shutdown.Unregister(handlerName)
if err := c.unpause(); err != nil { if err := c.unpause(); err != nil {
logrus.Errorf("Unpausing container %q: %v", c.ID(), err) logrus.Errorf("Unpausing container %q: %v", c.ID(), err)
} }