From 83e6e4ccdd925fa25500cff9e4b631b2c5d157cb Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Mon, 12 Oct 2020 15:10:52 -0400 Subject: [PATCH] Enable masking stop signals within container creation Expand the use of the Shutdown package such that we now use it to handle signals any time we run Libpod. From there, add code to container creation to use the Inhibit function to prevent a shutdown from occuring during the critical parts of container creation. We also need to turn off signal handling when --sig-proxy is invoked - we don't want to catch the signals ourselves then, but instead to forward them into the container via the existing sig-proxy handler. Fixes #7941 Signed-off-by: Matthew Heon --- libpod/runtime.go | 13 +++++++++++++ libpod/runtime_ctr.go | 5 +++++ libpod/shutdown/handler.go | 8 ++++++++ pkg/api/server/server.go | 10 ++++------ pkg/domain/infra/abi/terminal/sigproxy_linux.go | 5 +++++ 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/libpod/runtime.go b/libpod/runtime.go index 7da8b181f4..1118264f0e 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -17,6 +17,7 @@ import ( "github.com/containers/podman/v2/libpod/events" "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/libpod/lock" + "github.com/containers/podman/v2/libpod/shutdown" "github.com/containers/podman/v2/pkg/cgroups" "github.com/containers/podman/v2/pkg/registries" "github.com/containers/podman/v2/pkg/rootless" @@ -174,9 +175,21 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R } } + if err := shutdown.Start(); err != nil { + return nil, errors.Wrapf(err, "error starting shutdown signal handler") + } + if err := makeRuntime(ctx, runtime); err != nil { return nil, err } + + if err := shutdown.Register("libpod", func() error { + os.Exit(1) + return nil + }); err != nil { + logrus.Errorf("Error registering shutdown handler for libpod: %v", err) + } + return runtime, nil } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 51b4c5f039..de73a9ff35 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -12,6 +12,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/libpod/events" + "github.com/containers/podman/v2/libpod/shutdown" "github.com/containers/podman/v2/pkg/cgroups" "github.com/containers/podman/v2/pkg/rootless" "github.com/containers/storage" @@ -149,6 +150,10 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai return nil, err } + // Inhibit shutdown until creation succeeds + shutdown.Inhibit() + defer shutdown.Uninhibit() + // Allocate a lock for the container lock, err := r.lockManager.AllocateLock() if err != nil { diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go index 79f236ab6f..7abaf065b9 100644 --- a/libpod/shutdown/handler.go +++ b/libpod/shutdown/handler.go @@ -84,6 +84,10 @@ func Uninhibit() { // Register registers a function that will be executed when Podman is terminated // by a signal. func Register(name string, handler func() error) error { + if handlers == nil { + handlers = make(map[string]func() error) + } + if _, ok := handlers[name]; ok { return errors.Errorf("handler with name %s already exists", name) } @@ -95,6 +99,10 @@ func Register(name string, handler func() error) error { // Unregister un-registers a given shutdown handler. func Unregister(name string) error { + if handlers == nil { + handlers = make(map[string]func() error) + } + if _, ok := handlers[name]; !ok { return errors.Errorf("no handler with name %s found", name) } diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index cc5b45a651..24ad1874b5 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -190,6 +190,9 @@ func (s *APIServer) Serve() error { }); err != nil { return err } + // Unregister the libpod handler, which just calls exit(1). + // Ignore errors if it doesn't exist. + _ = shutdown.Unregister("libpod") errChan := make(chan error, 1) @@ -226,12 +229,7 @@ func (s *APIServer) Serve() error { errChan <- nil }() - select { - case err := <-errChan: - return err - } - - return nil + return <-errChan } // Shutdown is a clean shutdown waiting on existing clients diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index f484e926c0..0c586cf5c0 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -5,12 +5,17 @@ import ( "syscall" "github.com/containers/podman/v2/libpod" + "github.com/containers/podman/v2/libpod/shutdown" "github.com/containers/podman/v2/pkg/signal" "github.com/sirupsen/logrus" ) // ProxySignals ... func ProxySignals(ctr *libpod.Container) { + // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going + // to the container now. + shutdown.Stop() + sigBuffer := make(chan os.Signal, 128) signal.CatchAll(sigBuffer)