Skip to content

Commit

Permalink
machine applehv: create better error on start failure
Browse files Browse the repository at this point in the history
If gvproxy or vfkit exit we can error right away, so while we wait for
the socket to get ready we also keep checking the process status with
wait4() and WNOHANG so it does not block forever.

This is completely untested as I do not have acces to apple machine.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>

<MH: Added no new tests needed to pass CI>
[NO NEW TESTS NEEDED]

Signed-off-by: Matt Heon <mheon@redhat.com>
  • Loading branch information
Luap99 authored and openshift-cherrypick-robot committed Nov 21, 2023
1 parent 698458d commit 697e66c
Showing 1 changed file with 50 additions and 3 deletions.
53 changes: 50 additions & 3 deletions pkg/machine/applehv/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package applehv

import (
"context"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -669,9 +670,36 @@ func (m *MacMachine) Start(name string, opts machine.StartOptions) error {
return err
}

err = <-readyChan
if err != nil {
return err
processErrChan := make(chan error)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
defer close(processErrChan)
for {
select {
case <-ctx.Done():
return
default:
}
if err := checkProcessRunning("vfkit", cmd.Process.Pid); err != nil {
processErrChan <- err
return
}
// lets poll status every half second
time.Sleep(500 * time.Millisecond)
}
}()

// wait for either socket or to be ready or process to have exited
select {
case err := <-processErrChan:
if err != nil {
return err
}
case err := <-readyChan:
if err != nil {
return err
}
}

logrus.Debug("ready notification received")
Expand Down Expand Up @@ -902,6 +930,10 @@ func (m *MacMachine) startHostNetworking() (string, machine.APIForwardingState,
if err == nil {
break
}
if err := checkProcessRunning("gvproxy", c.Process.Pid); err != nil {
// gvproxy is no longer running
return "", 0, err
}
logrus.Debugf("gvproxy unixgram socket %q not found: %v", m.GvProxySock.GetPath(), err)
// Sleep for 1/2 second
time.Sleep(500 * time.Millisecond)
Expand All @@ -914,6 +946,21 @@ func (m *MacMachine) startHostNetworking() (string, machine.APIForwardingState,
return forwardSock, state, nil
}

// checkProcessRunning checks non blocking if the pid exited
// returns nil if process is running otherwise an error if not
func checkProcessRunning(processName string, pid int) error {
var status syscall.WaitStatus
pid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, nil)
if err != nil {
return fmt.Errorf("failed to read %s process status: %w", processName, err)
}
if pid > 0 {
// child exited
return fmt.Errorf("%s exited unexpectedly with exit code %d", processName, status.ExitStatus())
}
return nil
}

func (m *MacMachine) setupAPIForwarding(cmd gvproxy.GvproxyCommand) (gvproxy.GvproxyCommand, string, machine.APIForwardingState) {
socket, err := m.forwardSocketPath()
if err != nil {
Expand Down

0 comments on commit 697e66c

Please sign in to comment.