mirror of
https://github.com/moby/buildkit.git
synced 2026-08-09 09:11:45 +00:00
Traces are now forwarded in a non-blocking goroutine when sent through the traces exporter. This prevents traces forwarded from the client from being stalled while waiting for an upstream uploader to appear. In addition, adds a shutdown context to `appcontext` that will only cancel when an interrupt has been received twice. One interrupt will signal the program should clean up and shut down, the second indicates we should skip shutdown procedures (more forceful), and the third will indicate that we should immediately terminate the program. This gives a bit more of a degree of control to shutdown procedures like the traces and metrics exporter so there's a difference between forcibly calling exit and just waiting a long time for the shutdown to happen. Includes a more aggressive shutdown timeout for `buildctl` that is similar to the export timeout on `docker-buildx` for the tracing shutdown as another preventative measure to ensure the CLI hangs up at an appropriate time interval. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
66 lines
1.5 KiB
Go
66 lines
1.5 KiB
Go
package appcontext
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/signal"
|
|
"sync"
|
|
|
|
"github.com/moby/buildkit/util/bklog"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Context returns a static context that reacts to termination signals of the
|
|
// running process. Useful in CLI tools.
|
|
func Context() context.Context {
|
|
initContexts()
|
|
return appContext
|
|
}
|
|
|
|
// Shutdown returns a static context that closes when multiple interrupt signals
|
|
// have been received to indicate a faster shutdown. Useful in CLI tools.
|
|
func Shutdown() context.Context {
|
|
initContexts()
|
|
return shutdownContext
|
|
}
|
|
|
|
var (
|
|
appContext context.Context
|
|
shutdownContext context.Context
|
|
initContextsOnce sync.Once
|
|
)
|
|
|
|
func initContexts() {
|
|
initContextsOnce.Do(func() {
|
|
signals := make(chan os.Signal, 2048)
|
|
signal.Notify(signals, terminationSignals...)
|
|
|
|
ctx := context.Background()
|
|
for _, f := range inits {
|
|
ctx = f(ctx) //nolint:fatcontext
|
|
}
|
|
|
|
ctx, cancel := context.WithCancelCause(ctx)
|
|
appContext = ctx //nolint:fatcontext
|
|
|
|
shutdownCtx, shutdownCancel := context.WithCancelCause(context.Background())
|
|
shutdownContext = shutdownCtx
|
|
|
|
// We just allow this goroutine to be orphaned since program termination
|
|
// will clean it up.
|
|
go func() {
|
|
<-signals
|
|
err := errors.New("got SIGTERM/SIGINT, forcing shutdown")
|
|
cancel(err)
|
|
|
|
<-signals
|
|
err = errors.New("got 2 SIGTERM/SIGINTs, skipping shutdown")
|
|
shutdownCancel(err)
|
|
|
|
<-signals
|
|
err = errors.New("got 3 SIGTERM/SIGINTs, forcibly terminating")
|
|
bklog.G(ctx).Fatal(err.Error())
|
|
}()
|
|
})
|
|
}
|