From 4a00488869af8e13d2b6c32f492529c82e938f0a Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 29 Oct 2026 08:39:25 +0000 Subject: [PATCH] mapper: read tracked peers under workMu in batcher tests A full map replaces the set with Clear then Store; an unlocked read between them failed TestOlderInitialMapLeavesNewerStreamsPeers. --- hscontrol/mapper/batcher_test.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/hscontrol/mapper/batcher_test.go b/hscontrol/mapper/batcher_test.go index f3e3fba9b..d629be7b5 100644 --- a/hscontrol/mapper/batcher_test.go +++ b/hscontrol/mapper/batcher_test.go @@ -2356,8 +2356,19 @@ func TestEvictedSessionLeavesPeerTrackingAlone(t *testing.T) { nc, ok := b.nodes.Load(target) require.True(t, ok) - _, sent := nc.lastSentPeers.Load(peer) - assert.True(t, sent, "the peer stays tracked as sent") + assert.True(t, tracked(nc, peer), "the peer stays tracked as sent") +} + +// tracked reports whether nc tracks id as sent. It reads under workMu, as +// the batcher does: a full map replaces the set with Clear then Store, so a +// read outside it can land between the two. +func tracked(nc *multiChannelNodeConn, id tailcfg.NodeID) bool { + nc.workMu.Lock() + defer nc.workMu.Unlock() + + _, ok := nc.lastSentPeers.Load(id) + + return ok } // TestOlderInitialMapLeavesNewerStreamsPeers keeps a stream whose initial map, @@ -2447,8 +2458,7 @@ func TestOlderInitialMapLeavesNewerStreamsPeers(t *testing.T) { nc, ok := b.nodes.Load(target) require.True(t, ok) - _, sent := nc.lastSentPeers.Load(peer) - assert.True(t, sent, "the peer stays tracked as sent") + assert.True(t, tracked(nc, peer), "the peer stays tracked as sent") for listed := false; !listed; { select { @@ -2976,11 +2986,6 @@ func TestAddNodeRemovalSurvivesPendingLoss(t *testing.T) { {"with_peer", 2}, } - tracked := func(nc *multiChannelNodeConn, id tailcfg.NodeID) bool { - _, ok := nc.lastSentPeers.Load(id) - return ok - } - recv := func(t *testing.T, ch <-chan *tailcfg.MapResponse) *tailcfg.MapResponse { t.Helper()