Skip to content

Commit f9f8b72

Browse files
xgopilotYangSen-qn
andcommitted
fix: prevent deadlock in IsEqual and improve time consistency in Resolve
1. Fix potential AB-BA deadlock in IsEqual() method: - Lock mutexes in consistent order based on pointer address - Prevents deadlock when two goroutines compare same values in reverse order 2. Improve time consistency in Resolve() method: - Re-capture timestamp after acquiring write lock - Ensures accurate expiration checks in the cleanup phase Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: YangSen-qn <49863787+YangSen-qn@users.noreply.github.com>
1 parent 6cc9a6a commit f9f8b72

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

storagev2/resolver/resolver.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"strconv"
1212
"sync"
1313
"time"
14+
"unsafe"
1415

1516
"github.com/qiniu/go-sdk/v7/internal/cache"
1617
"github.com/qiniu/go-sdk/v7/internal/log"
@@ -241,10 +242,11 @@ func (resolver *cacheResolver) Resolve(ctx context.Context, host string) ([]net.
241242
// If some IPs expired, clean them up
242243
if expiredCount > 0 {
243244
rcv.mu.Lock()
244-
// Double-check after acquiring write lock
245+
// Re-check with fresh timestamp after acquiring write lock
246+
nowLocked := time.Now()
245247
validIPs := make([]resolverCacheValueIP, 0, len(rcv.IPs)-expiredCount)
246248
for _, cacheValueIP := range rcv.IPs {
247-
if cacheValueIP.ExpiredAt.After(now) {
249+
if cacheValueIP.ExpiredAt.After(nowLocked) {
248250
validIPs = append(validIPs, cacheValueIP)
249251
}
250252
}
@@ -289,10 +291,16 @@ func (resolver cacheResolver) FeedbackBad(context.Context, string, []net.IP) {}
289291

290292
func (left *resolverCacheValue) IsEqual(rightValue cache.CacheValue) bool {
291293
if right, ok := rightValue.(*resolverCacheValue); ok {
292-
left.mu.RLock()
293-
defer left.mu.RUnlock()
294-
right.mu.RLock()
295-
defer right.mu.RUnlock()
294+
// Avoid deadlock by locking in consistent order based on pointer address
295+
first, second := left, right
296+
if uintptr(unsafe.Pointer(left)) > uintptr(unsafe.Pointer(right)) {
297+
first, second = right, left
298+
}
299+
300+
first.mu.RLock()
301+
defer first.mu.RUnlock()
302+
second.mu.RLock()
303+
defer second.mu.RUnlock()
296304

297305
if len(left.IPs) != len(right.IPs) {
298306
return false

0 commit comments

Comments
 (0)