|
|
|
|
@ -488,14 +488,17 @@ func (s *Server) listenOn(port int) error { |
|
|
|
|
// Close closes the server.
|
|
|
|
|
func (s *Server) Close() error { |
|
|
|
|
s.closeOnce.Do(func() { |
|
|
|
|
s.mu.Lock() |
|
|
|
|
defer s.mu.Unlock() |
|
|
|
|
s.uc4.Close() |
|
|
|
|
if s.uc6 != nil { |
|
|
|
|
s.uc6.Close() |
|
|
|
|
} |
|
|
|
|
close(s.closeCh) |
|
|
|
|
s.wg.Wait() |
|
|
|
|
// s.mu must not be held while s.wg.Wait'ing, otherwise we can
|
|
|
|
|
// deadlock. The goroutines we are waiting on to return can also
|
|
|
|
|
// acquire s.mu.
|
|
|
|
|
s.mu.Lock() |
|
|
|
|
defer s.mu.Unlock() |
|
|
|
|
clear(s.byVNI) |
|
|
|
|
clear(s.byDisco) |
|
|
|
|
s.vniPool = nil |
|
|
|
|
@ -564,6 +567,12 @@ func (s *Server) handlePacket(from netip.AddrPort, b []byte, rxSocket, otherAFSo |
|
|
|
|
|
|
|
|
|
func (s *Server) packetReadLoop(readFromSocket, otherSocket *net.UDPConn) { |
|
|
|
|
defer func() { |
|
|
|
|
// We intentionally close the [Server] if we encounter a socket read
|
|
|
|
|
// error below, at least until socket "re-binding" is implemented as
|
|
|
|
|
// part of http://go/corp/30118.
|
|
|
|
|
//
|
|
|
|
|
// Decrementing this [sync.WaitGroup] _before_ calling [Server.Close] is
|
|
|
|
|
// intentional as [Server.Close] waits on it.
|
|
|
|
|
s.wg.Done() |
|
|
|
|
s.Close() |
|
|
|
|
}() |
|
|
|
|
|