Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shutdown gracefully without os.Exit #7480

Merged
merged 3 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,14 @@ func startStandAlone(ctx *Context, appCreator types.AppCreator) error {
tmos.Exit(err.Error())
}

TrapSignal(func() {
defer func() {
if err = svr.Stop(); err != nil {
tmos.Exit(err.Error())
}
})
}()

// run forever (the node will not be returned)
select {}
// Wait for SIGINT or SIGTERM signal
return WaitForQuitSignals()
}

// legacyAminoCdc is used for the legacy REST API
Expand Down Expand Up @@ -290,7 +290,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App
}
}

TrapSignal(func() {
defer func() {
if tmNode.IsRunning() {
_ = tmNode.Stop()
}
Expand All @@ -308,8 +308,8 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App
}

ctx.Logger.Info("exiting...")
})
}()

// run forever (the node will not be returned)
select {}
// Wait for SIGINT or SIGTERM signal
return WaitForQuitSignals()
}
18 changes: 18 additions & 0 deletions server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"os/signal"
"path/filepath"
"strconv"
"syscall"
"time"

Expand Down Expand Up @@ -39,6 +40,15 @@ type Context struct {
Logger log.Logger
}

// ErrorCode contains the exit code for server exit.
type ErrorCode struct {
Code int
}

func (e ErrorCode) Error() string {
return strconv.Itoa(e.Code)
}

func NewDefaultContext() *Context {
return NewContext(viper.New(), tmcfg.DefaultConfig(), log.NewTMLogger(log.NewSyncWriter(os.Stdout)))
}
Expand Down Expand Up @@ -245,6 +255,14 @@ func TrapSignal(cleanupFunc func()) {
}()
}

// WaitForQuitSignals waits for SIGINT and SIGTERM and returns.
func WaitForQuitSignals() ErrorCode {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigs
return ErrorCode{Code: int(sig.(syscall.Signal)) + 128}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why adding 128?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that is the standard way you handle -signal process termination in UNIX (n+128)

}

func skipInterface(iface net.Interface) bool {
if iface.Flags&net.FlagUp == 0 {
return true // interface down
Expand Down
8 changes: 7 additions & 1 deletion simapp/simd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ package main
import (
"os"

"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/simapp/simd/cmd"
)

func main() {
rootCmd, _ := cmd.NewRootCmd()
if err := cmd.Execute(rootCmd); err != nil {
os.Exit(1)
switch e := err.(type) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we log an error as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exit code + logging information already provided by the underlying goroutines should do it all.

Copy link
Collaborator Author

@yihuang yihuang Oct 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current error output when received SIGTERM is like this:

Error: 143
Usage:
  chain-maind start [flags]

Flags:
  ...

maybe add an error string into the ErrorCode?

case server.ErrorCode:
os.Exit(e.Code)
default:
os.Exit(1)
}
}
}