Skip to content

Commit

Permalink
Enforce LIFO ordering for shutdown handlers
Browse files Browse the repository at this point in the history
This allows us to run both the Libpod and Server handlers at the
same time without unregistering one.

Also, pass the signal that killed us into the handlers, in case
they want to use it to determine what to do (e.g. what exit code
to set).

Signed-off-by: Matthew Heon <[email protected]>
  • Loading branch information
mheon committed Oct 13, 2020
1 parent 83e6e4c commit f58d2f5
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 17 deletions.
2 changes: 1 addition & 1 deletion libpod/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R
return nil, err
}

if err := shutdown.Register("libpod", func() error {
if err := shutdown.Register("libpod", func(sig os.Signal) error {
os.Exit(1)
return nil
}); err != nil {
Expand Down
42 changes: 30 additions & 12 deletions libpod/shutdown/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ import (
)

var (
stopped bool
sigChan chan os.Signal
cancelChan chan bool
handlers map[string]func() error
stopped bool
sigChan chan os.Signal
cancelChan chan bool
// Definitions of all on-shutdown handlers
handlers map[string]func(os.Signal) error
// Ordering that on-shutdown handlers will be invoked.
handlerOrder []string
shutdownInhibit sync.RWMutex
)

// Start begins handling SIGTERM and SIGINT and will run the given on-signal
// handlers when one is called. This can be cancelled by calling Stop().
func Start() error {
if sigChan != nil && !stopped {
if sigChan != nil {
// Already running, do nothing.
return nil
}
Expand All @@ -43,9 +46,14 @@ func Start() error {
case sig := <-sigChan:
logrus.Infof("Received shutdown signal %v, terminating!", sig)
shutdownInhibit.Lock()
for name, handler := range handlers {
for _, name := range handlerOrder {
handler, ok := handlers[name]
if !ok {
logrus.Errorf("Shutdown handler %s definition not found!", name)
continue
}
logrus.Infof("Invoking shutdown handler %s", name)
if err := handler(); err != nil {
if err := handler(sig); err != nil {
logrus.Errorf("Error running shutdown handler %s: %v", name, err)
}
}
Expand Down Expand Up @@ -82,32 +90,42 @@ 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 {
// by a signal. Handlers are invoked LIFO - the last handler registered is the
// first run.
func Register(name string, handler func(os.Signal) error) error {
if handlers == nil {
handlers = make(map[string]func() error)
handlers = make(map[string]func(os.Signal) error)
}

if _, ok := handlers[name]; ok {
return errors.Errorf("handler with name %s already exists", name)
}

handlers[name] = handler
handlerOrder = append([]string{name}, handlerOrder...)

return nil
}

// Unregister un-registers a given shutdown handler.
func Unregister(name string) error {
if handlers == nil {
handlers = make(map[string]func() error)
return nil
}

if _, ok := handlers[name]; !ok {
return errors.Errorf("no handler with name %s found", name)
return nil
}

delete(handlers, name)

newOrder := []string{}
for _, checkName := range handlerOrder {
if checkName != name {
newOrder = append(newOrder, checkName)
}
}
handlerOrder = newOrder

return nil
}
5 changes: 1 addition & 4 deletions pkg/api/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,11 @@ func (s *APIServer) Serve() error {
if err := shutdown.Start(); err != nil {
return err
}
if err := shutdown.Register("server", func() error {
if err := shutdown.Register("server", func(sig os.Signal) error {
return s.Shutdown()
}); 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)

Expand Down

0 comments on commit f58d2f5

Please sign in to comment.