mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-22 19:09:58 +00:00
tsnet: avoid deadlock on close
tsnet.Server.Close was calling listener.Close with the server mutex held, but the listener close method tries to grab that mutex, resulting in a deadlock. Co-authored-by: David Crawshaw <crawshaw@tailscale.com> Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/netip"
|
||||
@@ -344,3 +345,26 @@ func TestTailscaleIPs(t *testing.T) {
|
||||
sIp4, upIp4, sIp6, upIp6)
|
||||
}
|
||||
}
|
||||
|
||||
// TestListenerCleanup is a regression test to verify that s.Close doesn't
|
||||
// deadlock if a listener is still open.
|
||||
func TestListenerCleanup(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
controlURL := startControl(t)
|
||||
s1, _ := startServer(t, ctx, controlURL, "s1")
|
||||
|
||||
ln, err := s1.Listen("tcp", ":8081")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s1.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ln.Close(); !errors.Is(err, net.ErrClosed) {
|
||||
t.Fatalf("second ln.Close error: %v, want net.ErrClosed", err)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user