@@ -52,28 +52,26 @@ type virtualMachineWrapper struct {
5252// Hold all *os.File created via socketpair() so that they won't get garbage collected. f.FD() gets invalid if f gets garbage collected.
5353var vmNetworkFiles = make ([]* os.File , 1 )
5454
55- func startVM (ctx context.Context , inst * limatype.Instance , sshLocalPort int ) (* virtualMachineWrapper , chan error , error ) {
55+ func startVM (ctx context.Context , inst * limatype.Instance , sshLocalPort int ) (vm * virtualMachineWrapper , waitSSHLocalPortAccessible <- chan any , errCh chan error , err error ) {
5656 usernetClient , stopUsernet , err := startUsernet (ctx , inst )
5757 if err != nil {
58- return nil , nil , err
58+ return nil , nil , nil , err
5959 }
6060
6161 machine , err := createVM (ctx , inst )
6262 if err != nil {
63- return nil , nil , err
63+ return nil , nil , nil , err
6464 }
6565
6666 err = machine .Start ()
6767 if err != nil {
68- return nil , nil , err
68+ return nil , nil , nil , err
6969 }
7070
7171 wrapper := & virtualMachineWrapper {VirtualMachine : machine , stopped : false }
72+ notifySSHLocalPortAccessible := make (chan any )
73+ sendErrCh := make (chan error )
7274
73- errCh := make (chan error )
74-
75- waitSSHLocalPortAccessible := make (chan struct {})
76- defer close (waitSSHLocalPortAccessible )
7775 go func () {
7876 // Handle errors via errCh and handle stop vm during context close
7977 defer func () {
@@ -95,42 +93,44 @@ func startVM(ctx context.Context, inst *limatype.Instance, sshLocalPort int) (*v
9593 pidFile := filepath .Join (inst .Dir , filenames .PIDFile (* inst .Config .VMType ))
9694 if _ , err := os .Stat (pidFile ); ! errors .Is (err , os .ErrNotExist ) {
9795 logrus .Errorf ("pidfile %q already exists" , pidFile )
98- errCh <- err
96+ sendErrCh <- err
9997 }
10098 if err := os .WriteFile (pidFile , []byte (strconv .Itoa (os .Getpid ())+ "\n " ), 0o644 ); err != nil {
10199 logrus .Errorf ("error writing to pid fil %q" , pidFile )
102- errCh <- err
100+ sendErrCh <- err
103101 }
104102 logrus .Info ("[VZ] - vm state change: running" )
105103
106- usernetSSHLocalPort := sshLocalPort
107- useSSHOverVsock := true
108- if envVar := os .Getenv ("LIMA_SSH_OVER_VSOCK" ); envVar != "" {
109- b , err := strconv .ParseBool (envVar )
110- if err != nil {
111- logrus .WithError (err ).Warnf ("invalid LIMA_SSH_OVER_VSOCK value %q" , envVar )
112- } else {
113- useSSHOverVsock = b
104+ go func () {
105+ defer close (notifySSHLocalPortAccessible )
106+ usernetSSHLocalPort := sshLocalPort
107+ useSSHOverVsock := true
108+ if envVar := os .Getenv ("LIMA_SSH_OVER_VSOCK" ); envVar != "" {
109+ b , err := strconv .ParseBool (envVar )
110+ if err != nil {
111+ logrus .WithError (err ).Warnf ("invalid LIMA_SSH_OVER_VSOCK value %q" , envVar )
112+ } else {
113+ useSSHOverVsock = b
114+ }
114115 }
115- }
116- if ! useSSHOverVsock {
117- logrus .Info ("LIMA_SSH_OVER_VSOCK is false, skipping detection of SSH server on vsock port" )
118- } else if err := usernetClient .WaitOpeningSSHPort (ctx , inst ); err == nil {
119- hostAddress := net .JoinHostPort (inst .SSHAddress , strconv .Itoa (usernetSSHLocalPort ))
120- if err := wrapper .startVsockForwarder (ctx , 22 , hostAddress ); err == nil {
121- logrus .Infof ("Detected SSH server is listening on the vsock port; changed %s to proxy for the vsock port" , hostAddress )
122- usernetSSHLocalPort = 0 // disable gvisor ssh port forwarding
116+ if ! useSSHOverVsock {
117+ logrus .Info ("LIMA_SSH_OVER_VSOCK is false, skipping detection of SSH server on vsock port" )
118+ } else if err := usernetClient .WaitOpeningSSHPort (ctx , inst ); err == nil {
119+ hostAddress := net .JoinHostPort (inst .SSHAddress , strconv .Itoa (usernetSSHLocalPort ))
120+ if err := wrapper .startVsockForwarder (ctx , 22 , hostAddress ); err == nil {
121+ logrus .Infof ("Detected SSH server is listening on the vsock port; changed %s to proxy for the vsock port" , hostAddress )
122+ usernetSSHLocalPort = 0 // disable gvisor ssh port forwarding
123+ } else {
124+ logrus .WithError (err ).Warn ("Failed to detect SSH server on vsock port, falling back to usernet forwarder" )
125+ }
123126 } else {
124- logrus .WithError (err ).Warn ("Failed to detect SSH server on vsock port , falling back to usernet forwarder" )
127+ logrus .WithError (err ).Warn ("Failed to wait for the guest SSH server to become available , falling back to usernet forwarder" )
125128 }
126- } else {
127- logrus .WithError (err ).Warn ("Failed to wait for the guest SSH server to become available, falling back to usernet forwarder" )
128- }
129- err := usernetClient .ConfigureDriver (ctx , inst , usernetSSHLocalPort )
130- if err != nil {
131- errCh <- err
132- }
133- waitSSHLocalPortAccessible <- struct {}{}
129+ err := usernetClient .ConfigureDriver (ctx , inst , usernetSSHLocalPort )
130+ if err != nil {
131+ sendErrCh <- err
132+ }
133+ }()
134134 case vz .VirtualMachineStateStopped :
135135 logrus .Info ("[VZ] - vm state change: stopped" )
136136 wrapper .mu .Lock ()
@@ -140,15 +140,14 @@ func startVM(ctx context.Context, inst *limatype.Instance, sshLocalPort int) (*v
140140 if stopUsernet != nil {
141141 stopUsernet ()
142142 }
143- errCh <- errors .New ("vz driver state stopped" )
143+ sendErrCh <- errors .New ("vz driver state stopped" )
144144 default :
145145 logrus .Debugf ("[VZ] - vm state change: %q" , newState )
146146 }
147147 }
148148 }
149149 }()
150- <- waitSSHLocalPortAccessible
151- return wrapper , errCh , err
150+ return wrapper , notifySSHLocalPortAccessible , sendErrCh , err
152151}
153152
154153func startUsernet (ctx context.Context , inst * limatype.Instance ) (* usernet.Client , context.CancelFunc , error ) {
0 commit comments