diff --git a/cmd/compose/compose.go b/cmd/compose/compose.go index f432d7c02..cddcd3a4c 100644 --- a/cmd/compose/compose.go +++ b/cmd/compose/compose.go @@ -42,6 +42,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/docker/cli/cli-plugins/plugin" "github.com/docker/compose/v2/cmd/formatter" "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/compose" @@ -75,7 +76,7 @@ func AdaptCmd(fn CobraCommand) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() contextString := fmt.Sprintf("%s", ctx) - if !strings.HasSuffix(contextString, ".WithCancel") { // need to handle cancel + if !strings.Contains(contextString, ".WithCancel") || plugin.RunningStandalone() { // need to handle cancel cancellableCtx, cancel := context.WithCancel(cmd.Context()) ctx = cancellableCtx s := make(chan os.Signal, 1) diff --git a/pkg/compose/up.go b/pkg/compose/up.go index fb54a5965..8236adff0 100644 --- a/pkg/compose/up.go +++ b/pkg/compose/up.go @@ -31,7 +31,7 @@ import ( "github.com/hashicorp/go-multierror" ) -func (s *composeService) Up(ctx context.Context, project *types.Project, options api.UpOptions) error { +func (s *composeService) Up(ctx context.Context, project *types.Project, options api.UpOptions) error { //nolint:gocyclo err := progress.Run(ctx, tracing.SpanWrapFunc("project/up", tracing.ProjectOptions(project), func(ctx context.Context) error { err := s.create(ctx, project, options.Create) if err != nil { @@ -69,24 +69,31 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options doneCh := make(chan bool) eg.Go(func() error { first := true + gracefulTeardown := func() { + printer.Cancel() + fmt.Fprintln(s.stdinfo(), "Gracefully stopping... (press Ctrl+C again to force)") + eg.Go(func() error { + err := s.Stop(context.Background(), project.Name, api.StopOptions{ + Services: options.Create.Services, + Project: project, + }) + isTerminated = true + close(doneCh) + return err + }) + first = false + } for { select { case <-doneCh: return nil + case <-ctx.Done(): + if first { + gracefulTeardown() + } case <-signalChan: if first { - printer.Cancel() - fmt.Fprintln(s.stdinfo(), "Gracefully stopping... (press Ctrl+C again to force)") - eg.Go(func() error { - err := s.Stop(context.Background(), project.Name, api.StopOptions{ - Services: options.Create.Services, - Project: project, - }) - isTerminated = true - close(doneCh) - return err - }) - first = false + gracefulTeardown() } else { eg.Go(func() error { return s.Kill(context.Background(), project.Name, api.KillOptions{