From 9c968e617074b630e112bea3c1173e8a56f49b80 Mon Sep 17 00:00:00 2001 From: xgopilot Date: Tue, 11 Nov 2025 09:54:03 +0000 Subject: [PATCH] fix: resolve data race in cacheResolver.FeedbackGood method Create a copy of the cache value instead of modifying it in-place to avoid race conditions when multiple goroutines access the same resolverCacheValue concurrently. This fixes the data race detected by the Go race detector in the storagev2 cacheProvider. Fixes #172 Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: zhangzqs <34616640+zhangzqs@users.noreply.github.com> --- storagev2/resolver/resolver.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/storagev2/resolver/resolver.go b/storagev2/resolver/resolver.go index fe94a399..66fdc6f6 100644 --- a/storagev2/resolver/resolver.go +++ b/storagev2/resolver/resolver.go @@ -261,16 +261,25 @@ func (resolver cacheResolver) FeedbackGood(ctx context.Context, host string, ips rcv := cacheValue.(*resolverCacheValue) now := time.Now() anyIPLiveLonger := false - for i := range rcv.IPs { - if isIPContains(ips, rcv.IPs[i].IP) { - rcv.IPs[i].ExpiredAt = now.Add(resolver.cacheLifetime) + + // Create a copy of the cache value to avoid race conditions + newRcv := &resolverCacheValue{ + IPs: make([]resolverCacheValueIP, len(rcv.IPs)), + RefreshAfter: rcv.RefreshAfter, + ExpiredAt: rcv.ExpiredAt, + } + copy(newRcv.IPs, rcv.IPs) + + for i := range newRcv.IPs { + if isIPContains(ips, newRcv.IPs[i].IP) { + newRcv.IPs[i].ExpiredAt = now.Add(resolver.cacheLifetime) anyIPLiveLonger = true } } if anyIPLiveLonger { - rcv.RefreshAfter = now.Add(resolver.cacheRefreshAfter) - rcv.ExpiredAt = now.Add(resolver.cacheLifetime) - resolver.cache.Set(cacheKey, rcv) + newRcv.RefreshAfter = now.Add(resolver.cacheRefreshAfter) + newRcv.ExpiredAt = now.Add(resolver.cacheLifetime) + resolver.cache.Set(cacheKey, newRcv) } } }