Skip to content

Commit

Permalink
Fix race condition in getTCPAddrs
Browse files Browse the repository at this point in the history
  • Loading branch information
erikdubbelboer committed Oct 29, 2021
1 parent 528dd62 commit 6d4db9b
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions tcpdialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,8 @@ type tcpAddrEntry struct {
addrs []net.TCPAddr
addrsIdx uint32

pending int32
resolveTime time.Time
pending bool
}

// DefaultDNSCacheDuration is the duration for caching resolved TCP addresses
Expand All @@ -384,18 +384,21 @@ func (d *TCPDialer) tcpAddrsClean() {
func (d *TCPDialer) getTCPAddrs(addr string, dualStack bool) ([]net.TCPAddr, uint32, error) {
item, exist := d.tcpAddrsMap.Load(addr)
e, ok := item.(*tcpAddrEntry)
if exist && ok && e != nil && !e.pending && time.Since(e.resolveTime) > d.DNSCacheDuration {
e.pending = true
e = nil
if exist && ok && e != nil && time.Since(e.resolveTime) > d.DNSCacheDuration {
// Only let one goroutine re-resolve at a time.
if atomic.SwapInt32(&e.pending, 1) == 0 {
e = nil
}
}

if e == nil {
addrs, err := resolveTCPAddrs(addr, dualStack, d.Resolver)
if err != nil {
item, exist := d.tcpAddrsMap.Load(addr)
e, ok = item.(*tcpAddrEntry)
if exist && ok && e != nil && e.pending {
e.pending = false
if exist && ok && e != nil {
// Set pending to 0 so another goroutine can retry.
atomic.StoreInt32(&e.pending, 0)
}
return nil, 0, err
}
Expand Down

0 comments on commit 6d4db9b

Please sign in to comment.