Skip to content

Commit 25ea53a

Browse files
authored
wgengine/magicsock: fix relayManager deadlock (tailscale#17449) (tailscale#17511)
Updates tailscale/corp#32978 (cherry picked from commit e44e28e) Signed-off-by: Jordan Whited <jordan@tailscale.com>
1 parent 9961c09 commit 25ea53a

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

wgengine/magicsock/relaymanager.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,10 @@ func (r *relayManager) handleNewServerEndpointRunLoop(newServerEndpoint newRelay
758758
ctx: ctx,
759759
cancel: cancel,
760760
}
761-
if byServerDisco == nil {
761+
// We must look up byServerDisco again. The previous value may have been
762+
// deleted from the outer map when cleaning up duplicate work.
763+
byServerDisco, ok = r.handshakeWorkByServerDiscoByEndpoint[newServerEndpoint.wlb.ep]
764+
if !ok {
762765
byServerDisco = make(map[key.DiscoPublic]*relayHandshakeWork)
763766
r.handshakeWorkByServerDiscoByEndpoint[newServerEndpoint.wlb.ep] = byServerDisco
764767
}

wgengine/magicsock/relaymanager_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"tailscale.com/disco"
10+
udprelay "tailscale.com/net/udprelay/endpoint"
1011
"tailscale.com/types/key"
1112
"tailscale.com/util/set"
1213
)
@@ -78,3 +79,41 @@ func TestRelayManagerGetServers(t *testing.T) {
7879
t.Errorf("got %v != want %v", got, servers)
7980
}
8081
}
82+
83+
// Test for http://go/corp/32978
84+
func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
85+
rm := relayManager{}
86+
rm.init()
87+
<-rm.runLoopStoppedCh // prevent runLoop() from starting, we will inject/handle events in the test
88+
ep := &endpoint{}
89+
conn := newConn(t.Logf)
90+
ep.c = conn
91+
serverDisco := key.NewDisco().Public()
92+
rm.handleNewServerEndpointRunLoop(newRelayServerEndpointEvent{
93+
wlb: endpointWithLastBest{
94+
ep: ep,
95+
},
96+
se: udprelay.ServerEndpoint{
97+
ServerDisco: serverDisco,
98+
LamportID: 1,
99+
VNI: 1,
100+
},
101+
})
102+
rm.handleNewServerEndpointRunLoop(newRelayServerEndpointEvent{
103+
wlb: endpointWithLastBest{
104+
ep: ep,
105+
},
106+
se: udprelay.ServerEndpoint{
107+
ServerDisco: serverDisco,
108+
LamportID: 2,
109+
VNI: 2,
110+
},
111+
})
112+
rm.stopWorkRunLoop(ep)
113+
if len(rm.handshakeWorkByServerDiscoByEndpoint) != 0 ||
114+
len(rm.handshakeWorkByServerDiscoVNI) != 0 ||
115+
len(rm.handshakeWorkAwaitingPong) != 0 ||
116+
len(rm.addrPortVNIToHandshakeWork) != 0 {
117+
t.Fatal("stranded relayHandshakeWork state")
118+
}
119+
}

0 commit comments

Comments
 (0)