@@ -18,11 +18,11 @@ package compose
1818
1919import (
2020 "context"
21- "errors"
2221 "fmt"
23- "github.com/sirupsen/logrus"
2422 "os"
23+ "os/signal"
2524 "path/filepath"
25+ "syscall"
2626
2727 "github.com/docker/compose-cli/api/client"
2828 "github.com/docker/compose-cli/api/compose"
@@ -31,6 +31,7 @@ import (
3131 "github.com/docker/compose-cli/cli/formatter"
3232
3333 "github.com/compose-spec/compose-go/types"
34+ "github.com/sirupsen/logrus"
3435 "github.com/spf13/cobra"
3536)
3637
@@ -151,47 +152,35 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
151152 return nil
152153 }
153154
154- ctx , cancel := context .WithCancel (ctx )
155- listener := make (chan compose.ContainerExited )
156- exitCode := make (chan int )
155+ queue := make (chan compose.ContainerEvent )
156+ printer := printer {
157+ queue : queue ,
158+ }
159+
160+ stopFunc := func () error {
161+ ctx := context .Background ()
162+ _ , err := progress .Run (ctx , func (ctx context.Context ) (string , error ) {
163+ return "" , c .ComposeService ().Stop (ctx , project )
164+ })
165+ return err
166+ }
167+ signalChan := make (chan os.Signal , 1 )
168+ signal .Notify (signalChan , syscall .SIGINT , syscall .SIGTERM )
157169 go func () {
158- var aborting bool
159- for {
160- exit := <- listener
161- if opts .cascadeStop && ! aborting {
162- aborting = true
163- cancel ()
164- exitCode <- exit .Status
165- }
166- }
170+ <- signalChan
171+ fmt .Println ("Gracefully stopping..." )
172+ stopFunc () // nolint:errcheck
167173 }()
168174
169175 err = c .ComposeService ().Start (ctx , project , compose.StartOptions {
170- Attach : formatter .NewLogConsumer (ctx , os .Stdout ),
171- Listener : listener ,
176+ Attach : queue ,
172177 })
173-
174- if errors .Is (ctx .Err (), context .Canceled ) {
175- select {
176- case exit := <- exitCode :
177- fmt .Println ("Aborting on container exit..." )
178- err = stop (c , project )
179- logrus .Error (exit )
180- // os.Exit(exit)
181- default :
182- // cancelled by user
183- fmt .Println ("Gracefully stopping..." )
184- err = stop (c , project )
185- }
178+ if err != nil {
179+ return err
186180 }
187- return err
188- }
189181
190- func stop (c * client.Client , project * types.Project ) error {
191- ctx := context .Background ()
192- _ , err := progress .Run (ctx , func (ctx context.Context ) (string , error ) {
193- return "" , c .ComposeService ().Stop (ctx , project )
194- })
182+ _ , err = printer .run (ctx , opts .cascadeStop , stopFunc )
183+ // FIXME os.Exit
195184 return err
196185}
197186
@@ -235,3 +224,26 @@ func setup(ctx context.Context, opts composeOptions, services []string) (*client
235224
236225 return c , project , nil
237226}
227+
228+ type printer struct {
229+ queue chan compose.ContainerEvent
230+ }
231+
232+ func (p printer ) run (ctx context.Context , cascadeStop bool , stopFn func () error ) (int , error ) { //nolint:unparam
233+ consumer := formatter .NewLogConsumer (ctx , os .Stdout )
234+ for {
235+ event := <- p .queue
236+ switch event .Type {
237+ case compose .ContainerEventExit :
238+ consumer .Status (event .Service , event .Source , fmt .Sprintf ("exited with code %d" , event .ExitCode ))
239+ if cascadeStop {
240+ fmt .Println ("Aborting on container exit..." )
241+ err := stopFn ()
242+ logrus .Error (event .ExitCode )
243+ return event .ExitCode , err
244+ }
245+ case compose .ContainerEventLog :
246+ consumer .Log (event .Service , event .Source , event .Line )
247+ }
248+ }
249+ }
0 commit comments