Skip to content

Commit c641f27

Browse files
authored
Merge pull request #4081 from norio-nomura/ensure-closing-hostagent-before-canceling-context
Ensure closing HostAgent before canceling context
2 parents d898a7d + fef24e5 commit c641f27

File tree

3 files changed

+44
-32
lines changed

3 files changed

+44
-32
lines changed

pkg/hostagent/hostagent.go

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ type HostAgent struct {
6060
portForwarder *portForwarder // legacy SSH port forwarder
6161
grpcPortForwarder *portfwd.Forwarder
6262

63-
onClose []func() error // LIFO
63+
onClose []func() error // LIFO
64+
onCloseMu sync.Mutex
6465

6566
driver driver.Driver
6667
signalCh chan os.Signal
@@ -460,26 +461,19 @@ func (a *HostAgent) startRoutinesAndWait(ctx context.Context, errCh <-chan error
460461
stRunning.Running = true
461462
a.emitEvent(ctx, events.Event{Status: stRunning})
462463
}()
463-
for {
464-
select {
465-
case driverErr := <-errCh:
466-
logrus.Infof("Driver stopped due to error: %q", driverErr)
467-
cancelHA()
468-
if closeErr := a.close(); closeErr != nil {
469-
logrus.WithError(closeErr).Warn("an error during shutting down the host agent")
470-
}
471-
err := a.driver.Stop(ctx)
472-
return err
473-
case sig := <-a.signalCh:
474-
logrus.Infof("Received %s, shutting down the host agent", osutil.SignalName(sig))
475-
cancelHA()
476-
if closeErr := a.close(); closeErr != nil {
477-
logrus.WithError(closeErr).Warn("an error during shutting down the host agent")
478-
}
479-
err := a.driver.Stop(ctx)
480-
return err
481-
}
482-
}
464+
// wait for either the driver to stop or a signal to shut down
465+
select {
466+
case driverErr := <-errCh:
467+
logrus.Infof("Driver stopped due to error: %q", driverErr)
468+
case sig := <-a.signalCh:
469+
logrus.Infof("Received %s, shutting down the host agent", osutil.SignalName(sig))
470+
}
471+
// close the host agent routines before cancelling the context
472+
if closeErr := a.close(); closeErr != nil {
473+
logrus.WithError(closeErr).Warn("an error during shutting down the host agent")
474+
}
475+
cancelHA()
476+
return a.driver.Stop(ctx)
483477
}
484478

485479
func (a *HostAgent) Info(_ context.Context) (*hostagentapi.Info, error) {
@@ -500,7 +494,7 @@ func (a *HostAgent) startHostAgentRoutines(ctx context.Context) error {
500494
}
501495
logrus.Info(msg)
502496
}
503-
a.onClose = append(a.onClose, func() error {
497+
a.cleanUp(func() error {
504498
logrus.Debugf("shutting down the SSH master")
505499
if exitMasterErr := ssh.ExitMaster(a.instSSHAddress, a.sshLocalPort, a.sshConfig); exitMasterErr != nil {
506500
logrus.WithError(exitMasterErr).Warn("failed to exit SSH master")
@@ -529,7 +523,7 @@ sudo chown -R "${USER}" /run/host-services`
529523
if err != nil {
530524
errs = append(errs, err)
531525
}
532-
a.onClose = append(a.onClose, func() error {
526+
a.cleanUp(func() error {
533527
var unmountErrs []error
534528
for _, m := range mounts {
535529
if unmountErr := m.close(); unmountErr != nil {
@@ -540,7 +534,7 @@ sudo chown -R "${USER}" /run/host-services`
540534
})
541535
}
542536
if len(a.instConfig.AdditionalDisks) > 0 {
543-
a.onClose = append(a.onClose, func() error {
537+
a.cleanUp(func() error {
544538
var unlockErrs []error
545539
for _, d := range a.instConfig.AdditionalDisks {
546540
disk, inspectErr := store.InspectDisk(d.Name)
@@ -599,7 +593,7 @@ sudo chown -R "${USER}" /run/host-services`
599593
errs = append(errs, err)
600594
}
601595
}
602-
a.onClose = append(a.onClose, func() error {
596+
a.cleanUp(func() error {
603597
var rmErrs []error
604598
for _, rule := range a.instConfig.CopyToHost {
605599
if rule.DeleteOnStop {
@@ -614,7 +608,17 @@ sudo chown -R "${USER}" /run/host-services`
614608
return errors.Join(errs...)
615609
}
616610

611+
// cleanUp registers a cleanup function to be called when the host agent is stopped.
612+
// The cleanup functions are called before the context is cancelled, in the reverse order of their registration.
613+
func (a *HostAgent) cleanUp(fn func() error) {
614+
a.onCloseMu.Lock()
615+
defer a.onCloseMu.Unlock()
616+
a.onClose = append(a.onClose, fn)
617+
}
618+
617619
func (a *HostAgent) close() error {
620+
a.onCloseMu.Lock()
621+
defer a.onCloseMu.Unlock()
618622
logrus.Infof("Shutting down the host agent")
619623
var errs []error
620624
for i := len(a.onClose) - 1; i >= 0; i-- {
@@ -643,7 +647,7 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
643647
localUnix := filepath.Join(a.instDir, filenames.GuestAgentSock)
644648
remoteUnix := "/run/lima-guestagent.sock"
645649

646-
a.onClose = append(a.onClose, func() error {
650+
a.cleanUp(func() error {
647651
logrus.Debugf("Stop forwarding unix sockets")
648652
var errs []error
649653
for _, rule := range a.instConfig.PortForwards {
@@ -677,6 +681,9 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
677681
}
678682
}()
679683

684+
// ensure close before ctx is cancelled
685+
a.cleanUp(a.grpcPortForwarder.Close)
686+
680687
for {
681688
if a.client == nil || !isGuestAgentSocketAccessible(ctx, a.client) {
682689
if a.driver.ForwardGuestAgent() {
@@ -809,7 +816,6 @@ func (a *HostAgent) processGuestAgentEvents(ctx context.Context, client *guestag
809816
a.grpcPortForwarder.OnEvent(ctx, client, ev)
810817
}
811818
}
812-
defer a.grpcPortForwarder.Close()
813819

814820
if err := client.Events(ctx, onEvent); err != nil {
815821
if status.Code(err) == codes.Canceled {

pkg/portfwd/forward.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ func NewPortForwarder(rules []limatype.PortForward, ignoreTCP, ignoreUDP bool) *
3434
}
3535
}
3636

37-
func (fw *Forwarder) Close() {
38-
fw.closableListeners.Close()
37+
func (fw *Forwarder) Close() error {
38+
return fw.closableListeners.Close()
3939
}
4040

4141
func (fw *Forwarder) OnEvent(ctx context.Context, client *guestagentclient.GuestAgentClient, ev *api.Event) {

pkg/portfwd/listener.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,25 @@ func NewClosableListener() *ClosableListeners {
3838
}
3939
}
4040

41-
func (p *ClosableListeners) Close() {
41+
func (p *ClosableListeners) Close() error {
4242
p.listenersRW.Lock()
4343
defer p.listenersRW.Unlock()
44+
var errs []error
4445
for _, listener := range p.listeners {
45-
listener.Close()
46+
if err := listener.Close(); err != nil {
47+
errs = append(errs, err)
48+
}
4649
}
4750
clear(p.listeners)
4851
p.udpListenersRW.Lock()
4952
defer p.udpListenersRW.Unlock()
5053
for _, listener := range p.udpListeners {
51-
listener.Close()
54+
if err := listener.Close(); err != nil {
55+
errs = append(errs, err)
56+
}
5257
}
5358
clear(p.udpListeners)
59+
return errors.Join(errs...)
5460
}
5561

5662
func (p *ClosableListeners) Forward(ctx context.Context, client *guestagentclient.GuestAgentClient,

0 commit comments

Comments
 (0)