Skip to content

Commit

Permalink
fix deadlock when concurrently closing server and transport (#4332)
Browse files Browse the repository at this point in the history
* server: fix deadlock when closing concurrently with transport

* add test for checking no deadlock
  • Loading branch information
sukunrt committed Mar 3, 2024
1 parent ba1fbbe commit d6269b7
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 9 deletions.
22 changes: 13 additions & 9 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ type baseServer struct {
protocol.Version,
) quicConn

closeOnce sync.Once
closeMx sync.Mutex
errorChan chan struct{} // is closed when the server is closed
closeErr error
running chan struct{} // closed as soon as run() returns
Expand Down Expand Up @@ -338,15 +338,19 @@ func (s *baseServer) Close() error {
}

func (s *baseServer) close(e error, notifyOnClose bool) {
s.closeOnce.Do(func() {
s.closeErr = e
close(s.errorChan)
s.closeMx.Lock()
if s.closeErr != nil {
s.closeMx.Unlock()
return
}
s.closeErr = e
close(s.errorChan)
<-s.running
s.closeMx.Unlock()

<-s.running
if notifyOnClose {
s.onClose()
}
})
if notifyOnClose {
s.onClose()
}
}

// Addr returns the server's network address
Expand Down
21 changes: 21 additions & 0 deletions transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,27 @@ var _ = Describe("Transport", func() {
tr.Close()
})

It("closes transport concurrently with listener", func() {
// try 10 times to trigger race conditions
for i := 0; i < 10; i++ {
packetChan := make(chan packetToRead)
tr := &Transport{Conn: newMockPacketConn(packetChan)}
ln, err := tr.Listen(&tls.Config{}, nil)
Expect(err).ToNot(HaveOccurred())
ch := make(chan bool)
// Close transport and listener concurrently.
go func() {
ch <- true
Expect(ln.Close()).To(Succeed())
ch <- true
}()
<-ch
close(packetChan)
Expect(tr.Close()).To(Succeed())
<-ch
}
})

It("drops unparseable QUIC packets", func() {
addr := &net.UDPAddr{IP: net.IPv4(9, 8, 7, 6), Port: 1234}
packetChan := make(chan packetToRead)
Expand Down

0 comments on commit d6269b7

Please sign in to comment.