@@ -21,6 +21,7 @@ import (
21
21
"fmt"
22
22
"os"
23
23
"os/signal"
24
+ "sync/atomic"
24
25
"syscall"
25
26
26
27
"github.com/compose-spec/compose-go/v2/types"
@@ -65,9 +66,10 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
65
66
// we might miss a signal while setting up the second channel read
66
67
// (this is also why signal.Notify is used vs signal.NotifyContext)
67
68
signalChan := make (chan os.Signal , 2 )
68
- signal .Notify (signalChan , syscall .SIGINT , syscall .SIGTERM )
69
69
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
71
73
printer := newLogPrinter (options .Start .Attach )
72
74
73
75
doneCh := make (chan bool )
@@ -78,12 +80,11 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
78
80
formatter .ClearLine ()
79
81
fmt .Fprintln (s .stdinfo (), "Gracefully stopping... (press Ctrl+C again to force)" )
80
82
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 {
82
84
Services : options .Create .Services ,
83
85
Project : project ,
84
86
})
85
- isTerminated = true
86
- close (doneCh )
87
+ isTerminated .Store (true )
87
88
return err
88
89
})
89
90
first = false
@@ -120,7 +121,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
120
121
break
121
122
}
122
123
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 {
124
125
Services : options .Create .Services ,
125
126
Project : project ,
126
127
All : true ,
@@ -165,18 +166,17 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
165
166
})
166
167
}
167
168
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
171
172
return err
172
173
}
173
174
175
+ // Signal for the signal-handler goroutines to stop
176
+ close (doneCh )
177
+
174
178
printer .Stop ()
175
179
176
- if ! isTerminated {
177
- // signal for the signal-handler goroutines to stop
178
- close (doneCh )
179
- }
180
180
err = eg .Wait ().ErrorOrNil ()
181
181
if exitCode != 0 {
182
182
errMsg := ""
0 commit comments