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

Up: teardown when command context is cancelled
This commit is contained in:
Milas Bowman 2024-01-02 15:48:14 -05:00 committed by GitHub
commit 06af729dc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 14 deletions

View File

@ -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)

View File

@ -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{