@@ -21,6 +21,7 @@ import (
2121 "fmt"
2222 "os"
2323 "os/signal"
24+ "sync/atomic"
2425 "syscall"
2526
2627 "github.com/compose-spec/compose-go/v2/types"
@@ -65,9 +66,10 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
6566 // we might miss a signal while setting up the second channel read
6667 // (this is also why signal.Notify is used vs signal.NotifyContext)
6768 signalChan := make (chan os.Signal , 2 )
68- signal .Notify (signalChan , syscall .SIGINT , syscall .SIGTERM )
6969 defer close (signalChan )
70- var isTerminated bool
70+ signal .Notify (signalChan , syscall .SIGINT , syscall .SIGTERM )
71+ defer signal .Stop (signalChan )
72+ var isTerminated atomic.Bool
7173 printer := newLogPrinter (options .Start .Attach )
7274
7375 doneCh := make (chan bool )
@@ -78,12 +80,11 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
7880 formatter .ClearLine ()
7981 fmt .Fprintln (s .stdinfo (), "Gracefully stopping... (press Ctrl+C again to force)" )
8082 eg .Go (func () error {
81- err := s .Stop (context .Background ( ), project .Name , api.StopOptions {
83+ err := s .Stop (context .WithoutCancel ( ctx ), project .Name , api.StopOptions {
8284 Services : options .Create .Services ,
8385 Project : project ,
8486 })
85- isTerminated = true
86- close (doneCh )
87+ isTerminated .Store (true )
8788 return err
8889 })
8990 first = false
@@ -120,7 +121,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
120121 break
121122 }
122123 eg .Go (func () error {
123- err := s .kill (context .Background ( ), project .Name , api.KillOptions {
124+ err := s .kill (context .WithoutCancel ( ctx ), project .Name , api.KillOptions {
124125 Services : options .Create .Services ,
125126 Project : project ,
126127 All : true ,
@@ -165,18 +166,17 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
165166 })
166167 }
167168
168- // We don't use parent (cancelable) context as we manage sigterm to stop the stack
169- err = s .start (context .Background ( ), project .Name , options .Start , printer .HandleEvent )
170- if err != nil && ! isTerminated { // Ignore error if the process is terminated
169+ // We use the parent context without cancelation as we manage sigterm to stop the stack
170+ err = s .start (context .WithoutCancel ( ctx ), project .Name , options .Start , printer .HandleEvent )
171+ if err != nil && ! isTerminated . Load () { // Ignore error if the process is terminated
171172 return err
172173 }
173174
175+ // Signal for the signal-handler goroutines to stop
176+ close (doneCh )
177+
174178 printer .Stop ()
175179
176- if ! isTerminated {
177- // signal for the signal-handler goroutines to stop
178- close (doneCh )
179- }
180180 err = eg .Wait ().ErrorOrNil ()
181181 if exitCode != 0 {
182182 errMsg := ""
0 commit comments