@@ -268,6 +268,8 @@ type Machine struct {
268268 startOnce sync.Once
269269 // exitCh is a channel which gets closed when the VMM exits
270270 exitCh chan struct {}
271+ // shutdownCh is a channel which gets closed when the VM is shutdown
272+ shutdownCh chan struct {}
271273 // fatalErr records an error that either stops or prevent starting the VMM
272274 fatalErr error
273275
@@ -360,8 +362,9 @@ func configureBuilder(builder VMCommandBuilder, cfg Config) VMCommandBuilder {
360362// provided Config.
361363func NewMachine (ctx context.Context , cfg Config , opts ... Opt ) (* Machine , error ) {
362364 m := & Machine {
363- exitCh : make (chan struct {}),
364- cleanupCh : make (chan struct {}),
365+ exitCh : make (chan struct {}),
366+ shutdownCh : make (chan struct {}),
367+ cleanupCh : make (chan struct {}),
365368 }
366369
367370 if cfg .VMID == "" {
@@ -460,6 +463,9 @@ func (m *Machine) Start(ctx context.Context) error {
460463// Shutdown requests a clean shutdown of the VM by sending CtrlAltDelete on the virtual keyboard
461464func (m * Machine ) Shutdown (ctx context.Context ) error {
462465 m .logger .Debug ("Called machine.Shutdown()" )
466+
467+ close (m .shutdownCh )
468+
463469 if runtime .GOARCH != "arm64" {
464470 return m .sendCtrlAltDel (ctx )
465471 } else {
@@ -591,11 +597,10 @@ func (m *Machine) startVMM(ctx context.Context) error {
591597
592598 // If using daemonized jailer and parent exits cleanly,
593599 // this is expected behavior. Don't treat it as an error.
594- // We return immediately and allow subsequent functions
595- // (such as waitForSocket) to send any errors to channels.
600+ // We instead wait for closure of shutdownCh from m.Shutdown().
596601 if m .Cfg .JailerCfg != nil && m .Cfg .JailerCfg .Daemonize && waitErr == nil {
597602 m .logger .Debugf ("jailer parent exited (expected for daemonized mode)" )
598- return
603+ <- m . shutdownCh
599604 }
600605
601606 if waitErr != nil {
0 commit comments