Jelajahi Sumber

Merge pull request #11292 from laurazard/update-cli-signal-handling

Up: teardown when command context is cancelled
Milas Bowman 1 tahun lalu
induk
melakukan
06af729dc8
2 mengubah file dengan 22 tambahan dan 14 penghapusan
  1. 2 1
      cmd/compose/compose.go
  2. 20 13
      pkg/compose/up.go

+ 2 - 1
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)

+ 20 - 13
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{