@@ -7,14 +7,12 @@ import (
77 "io"
88 "net/url"
99 "os"
10- "os/signal "
10+ "os/exec "
1111 "path"
1212 "path/filepath"
1313 "sort"
1414 "strconv"
1515 "strings"
16- "syscall"
17- "time"
1816
1917 dockertypes "github.com/docker/docker/api/types"
2018 "github.com/docker/docker/api/types/container"
@@ -148,7 +146,7 @@ type flags struct {
148146 ethlink string
149147}
150148
151- func dockerCmd () * cobra.Command {
149+ func dockerCmd (ch chan func () error ) * cobra.Command {
152150 var flags flags
153151
154152 cmd := & cobra.Command {
@@ -287,7 +285,7 @@ func dockerCmd() *cobra.Command {
287285 return xerrors .Errorf ("wait for dockerd: %w" , err )
288286 }
289287
290- err = runDockerCVM (ctx , log , client , blog , flags )
288+ err = runDockerCVM (ctx , log , client , blog , ch , flags )
291289 if err != nil {
292290 // It's possible we failed because we ran out of disk while
293291 // pulling the image. We should restart the daemon and use
@@ -316,7 +314,7 @@ func dockerCmd() *cobra.Command {
316314 }()
317315
318316 log .Debug (ctx , "reattempting container creation" )
319- err = runDockerCVM (ctx , log , client , blog , flags )
317+ err = runDockerCVM (ctx , log , client , blog , ch , flags )
320318 }
321319 if err != nil {
322320 blog .Errorf ("Failed to run envbox: %v" , err )
@@ -359,7 +357,7 @@ func dockerCmd() *cobra.Command {
359357 return cmd
360358}
361359
362- func runDockerCVM (ctx context.Context , log slog.Logger , client dockerutil.DockerClient , blog buildlog.Logger , flags flags ) error {
360+ func runDockerCVM (ctx context.Context , log slog.Logger , client dockerutil.DockerClient , blog buildlog.Logger , shutdownCh chan func () error , flags flags ) error {
363361 fs := xunix .GetFS (ctx )
364362
365363 // Set our OOM score to something really unfavorable to avoid getting killed
@@ -692,6 +690,7 @@ func runDockerCVM(ctx context.Context, log slog.Logger, client dockerutil.Docker
692690 if err != nil {
693691 return xerrors .Errorf ("create exec: %w" , err )
694692 }
693+
695694 resp , err := client .ContainerExecAttach (ctx , bootstrapExec .ID , dockertypes.ExecStartCheck {})
696695 if err != nil {
697696 return xerrors .Errorf ("attach exec: %w" , err )
@@ -715,53 +714,31 @@ func runDockerCVM(ctx context.Context, log slog.Logger, client dockerutil.Docker
715714 }
716715 }()
717716
718- inspect , err := client .ContainerExecInspect (ctx , bootstrapExec .ID )
717+ // We can't just call ExecInspect because there's a race where the cmd
718+ // hasn't been assigned a PID yet.
719+ bootstrapPID , err := dockerutil .GetExecPID (ctx , client , bootstrapExec .ID )
719720 if err != nil {
720721 return xerrors .Errorf ("exec inspect: %w" , err )
721722 }
722- sigs := make (chan os.Signal , 1 )
723- signal .Notify (sigs , syscall .SIGINT , syscall .SIGTERM )
724- go func () {
725- err := func () error {
726- log .Info (ctx , "waiting for signal" )
727- sig := <- sigs
728- sigstr := "TERM"
729- if sig == syscall .SIGINT {
730- sigstr = "INT"
731- }
732- log .Debug (ctx , "received signal" , slog .F ("signal" , sigstr ))
733723
734- killExec , err := client .ContainerExecCreate (ctx , containerID , dockertypes.ExecConfig {
735- User : imgMeta .UID ,
736- Cmd : []string {"sh" , "-c" , fmt .Sprintf ("kill -%s %d" , sigstr , inspect .Pid )},
737- AttachStdout : true ,
738- AttachStderr : true ,
739- })
740- if err != nil {
741- return xerrors .Errorf ("create kill exec: %w" , err )
742- }
743-
744- err = dockerutil .WaitForExit (ctx , client , killExec .ID )
745- if err != nil {
746- return xerrors .Errorf ("wait for kill exec to complete: %w" , err )
747- }
724+ shutdownCh <- func () error {
725+ log .Debug (ctx , "killing container" , slog .F ("bootstrap_pid" , bootstrapPID ))
748726
749- err = dockerutil .WaitForExit (ctx , client , bootstrapExec .ID )
750- if err != nil {
751- return xerrors .Errorf ("wait for exit: %w" , err )
752- }
727+ // The PID returned is the PID _outside_ the container...
728+ out , err := exec .Command ("kill" , "-TERM" , strconv .Itoa (bootstrapPID )).CombinedOutput ()
729+ if err != nil {
730+ return xerrors .Errorf ("kill bootstrap process (%s): %w" , out , err )
731+ }
753732
754- return nil
755- }()
756- log .Info (ctx , "exiting envbox" , slog .Error (err ))
757- log .Sync ()
733+ log .Debug (ctx , "sent kill signal waiting for process to exit" )
734+ err = dockerutil .WaitForExit (ctx , client , bootstrapExec .ID )
758735 if err != nil {
759- os . Exit ( 1 )
736+ return xerrors . Errorf ( "wait for exit: %w" , err )
760737 }
761- os . Exit ( 0 )
762- }( )
763- log . Info ( ctx , "HELP" )
764- time . Sleep ( time . Second )
738+
739+ log . Debug ( ctx , "bootstrap process successfully exited" )
740+ return nil
741+ }
765742
766743 return nil
767744}
0 commit comments