| 612 | } |
| 613 | |
| 614 | func (s *Server) close() { |
| 615 | // Close listeners under s.mu, then release before the heavy shutdown |
| 616 | // operations. We must not hold s.mu during netstack.Close, lb.Shutdown, |
| 617 | // etc. because callbacks from gVisor (e.g. getTCPHandlerForFlow) |
| 618 | // acquire s.mu, and waiting for those goroutines while holding the lock |
| 619 | // would deadlock. |
| 620 | s.mu.Lock() |
| 621 | for _, ln := range s.listeners { |
| 622 | ln.closeLocked() |
| 623 | } |
| 624 | s.mu.Unlock() |
| 625 | |
| 626 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 627 | defer cancel() |
| 628 | var wg sync.WaitGroup |
| 629 | wg.Go(func() { |
| 630 | // Perform a best-effort final flush. |
| 631 | if s.logtail != nil { |
| 632 | s.logtail.Shutdown(ctx) |
| 633 | } |
| 634 | if s.logbuffer != nil { |
| 635 | s.logbuffer.Close() |
| 636 | } |
| 637 | }) |
| 638 | wg.Go(func() { |
| 639 | if s.localAPIServer != nil { |
| 640 | s.localAPIServer.Shutdown(ctx) |
| 641 | } |
| 642 | }) |
| 643 | |
| 644 | if s.shutdownCancel != nil { |
| 645 | s.shutdownCancel() |
| 646 | } |
| 647 | if s.netstack != nil { |
| 648 | s.netstack.Close() |
| 649 | } |
| 650 | if s.lb != nil { |
| 651 | s.lb.Shutdown() |
| 652 | } |
| 653 | if s.netMon != nil { |
| 654 | s.netMon.Close() |
| 655 | } |
| 656 | if s.dialer != nil { |
| 657 | s.dialer.Close() |
| 658 | } |
| 659 | if s.localAPIListener != nil { |
| 660 | s.localAPIListener.Close() |
| 661 | } |
| 662 | if s.loopbackListener != nil { |
| 663 | s.loopbackListener.Close() |
| 664 | } |
| 665 | |
| 666 | wg.Wait() |
| 667 | s.sys.Bus.Get().Close() |
| 668 | } |
| 669 | |
| 670 | func (s *Server) doInit() { |
| 671 | s.shutdownCtx, s.shutdownCancel = context.WithCancel(context.Background()) |