aboutsummaryrefslogtreecommitdiff
path: root/tcpdialer.go
diff options
context:
space:
mode:
authorGravatar Erik Dubbelboer <erik@dubbelboer.com> 2021-10-29 20:24:17 +0200
committerGravatar Erik Dubbelboer <erik@dubbelboer.com> 2021-10-29 20:24:17 +0200
commit6d4db9bb7ebb00084c15ad164a204452cacd1bd4 (patch)
tree88e880586982566e683909639fc3dd73f70788a7 /tcpdialer.go
parentfeat: ability to read body separate from header (#1130) (diff)
downloadfasthttp-6d4db9bb7ebb00084c15ad164a204452cacd1bd4.tar.gz
fasthttp-6d4db9bb7ebb00084c15ad164a204452cacd1bd4.tar.bz2
fasthttp-6d4db9bb7ebb00084c15ad164a204452cacd1bd4.zip
Fix race condition in getTCPAddrs
Diffstat (limited to 'tcpdialer.go')
-rw-r--r--tcpdialer.go15
1 files changed, 9 insertions, 6 deletions
diff --git a/tcpdialer.go b/tcpdialer.go
index 261f62e..20a766f 100644
--- a/tcpdialer.go
+++ b/tcpdialer.go
@@ -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
@@ -384,9 +384,11 @@ 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 {
@@ -394,8 +396,9 @@ func (d *TCPDialer) getTCPAddrs(addr string, dualStack bool) ([]net.TCPAddr, uin
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
}