From 9275a27a72f5b25248f5905ebf4677eb3e140215 Mon Sep 17 00:00:00 2001 From: Alano Terblanche <18033717+Benehiko@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:11:17 +0100 Subject: [PATCH] feat: cause on user-terminated context Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com> --- cmd/docker/docker.go | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index ab2dd08f7f15..0d190cbe2ad5 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -28,16 +28,43 @@ import ( "go.opentelemetry.io/otel" ) +var errCtxUserTerminated = errors.New("user terminated the process") + func main() { - err := dockerMain(context.Background()) - if err != nil && !errdefs.IsCancelled(err) && !errdefs.IsContext(err) { + ctx := context.Background() + err := dockerMain(ctx) + if err != nil && !errdefs.IsCancelled(err) && !errors.Is(err, errCtxUserTerminated) { _, _ = fmt.Fprintln(os.Stderr, err) os.Exit(getExitCode(err)) } } +func notifyContext(ctx context.Context, signals ...os.Signal) (context.Context, context.CancelFunc) { + ch := make(chan os.Signal, 1) + signal.Notify(ch, signals...) + + ctx, cancel := context.WithCancelCause(ctx) + + go func() { + select { + case <-ctx.Done(): + signal.Stop(ch) + return + case <-ch: + cancel(errCtxUserTerminated) + signal.Stop(ch) + return + } + }() + + return ctx, func() { + signal.Stop(ch) + cancel(nil) + } +} + func dockerMain(ctx context.Context) error { - ctx, cancelNotify := signal.NotifyContext(ctx, platformsignals.TerminationSignals...) + ctx, cancelNotify := notifyContext(ctx, platformsignals.TerminationSignals...) defer cancelNotify() dockerCli, err := command.NewDockerCli(command.WithBaseContext(ctx))