Merge pull request #5970 from cpuguy83/cancel_on_signal

This commit is contained in:
Fu Wei 2021-09-16 09:26:22 +08:00 committed by GitHub
commit 7d6e9773ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 24 deletions

View File

@ -111,13 +111,15 @@ can be used and modified as necessary as a custom configuration.`
}
app.Action = func(context *cli.Context) error {
var (
start = time.Now()
signals = make(chan os.Signal, 2048)
serverC = make(chan *server.Server, 1)
ctx = gocontext.Background()
config = defaultConfig()
start = time.Now()
signals = make(chan os.Signal, 2048)
serverC = make(chan *server.Server, 1)
ctx, cancel = gocontext.WithCancel(gocontext.Background())
config = defaultConfig()
)
defer cancel()
// Only try to load the config if it either exists, or the user explicitly
// told us to load this path.
configPath := context.GlobalString("config")
@ -161,7 +163,7 @@ can be used and modified as necessary as a custom configuration.`
return nil
}
done := handleSignals(ctx, signals, serverC)
done := handleSignals(ctx, signals, serverC, cancel)
// start the signal handler as soon as we can to make sure that
// we don't miss any signals during boot
signal.Notify(signals, handledSignals...)
@ -193,18 +195,56 @@ can be used and modified as necessary as a custom configuration.`
"revision": version.Revision,
}).Info("starting containerd")
server, err := server.New(ctx, config)
if err != nil {
return err
type srvResp struct {
s *server.Server
err error
}
// run server initialization in a goroutine so we don't end up blocking important things like SIGTERM handling
// while the server is initializing.
// As an example opening the bolt database will block forever if another containerd is already running and containerd
// will have to be be `kill -9`'ed to recover.
chsrv := make(chan srvResp)
go func() {
defer close(chsrv)
server, err := server.New(ctx, config)
if err != nil {
select {
case chsrv <- srvResp{err: err}:
case <-ctx.Done():
}
return
}
// Launch as a Windows Service if necessary
if err := launchService(server, done); err != nil {
logrus.Fatal(err)
}
select {
case <-ctx.Done():
server.Stop()
case chsrv <- srvResp{s: server}:
}
}()
var server *server.Server
select {
case <-ctx.Done():
return ctx.Err()
case r := <-chsrv:
if r.err != nil {
return err
}
server = r.s
}
// Launch as a Windows Service if necessary
if err := launchService(server, done); err != nil {
logrus.Fatal(err)
// We don't send the server down serverC directly in the goroutine above because we need it lower down.
select {
case <-ctx.Done():
return ctx.Err()
case serverC <- server:
}
serverC <- server
if config.Debug.Address != "" {
var l net.Listener
if isLocalAddress(config.Debug.Address) {

View File

@ -36,7 +36,7 @@ var handledSignals = []os.Signal{
unix.SIGPIPE,
}
func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *server.Server) chan struct{} {
func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *server.Server, cancel func()) chan struct{} {
done := make(chan struct{}, 1)
go func() {
var server *server.Server
@ -61,11 +61,10 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
log.G(ctx).WithError(err).Error("notify stopping failed")
}
if server == nil {
close(done)
return
cancel()
if server != nil {
server.Stop()
}
server.Stop()
close(done)
return
}

View File

@ -39,7 +39,7 @@ var (
}
)
func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *server.Server) chan struct{} {
func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *server.Server, cancel func()) chan struct{} {
done := make(chan struct{})
go func() {
var server *server.Server
@ -54,12 +54,12 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
log.G(ctx).WithError(err).Error("notify stopping failed")
}
if server == nil {
close(done)
return
cancel()
if server != nil {
server.Stop()
}
server.Stop()
close(done)
return
}
}
}()