diff options
author | Ian Lance Taylor <iant@golang.org> | 2018-03-15 11:55:30 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2018-03-16 13:39:38 +0000 |
commit | bd859439e72a0c48c64259f7de9f175aae3b9c37 (patch) | |
tree | 9364a5653d1d0e570781d8a640383645c74a35b4 /src/net/lookup.go | |
parent | 0b20aece1aa4782070660a80dc4cf87c183533c9 (diff) | |
download | go-bd859439e72a0c48c64259f7de9f175aae3b9c37.tar.gz go-bd859439e72a0c48c64259f7de9f175aae3b9c37.zip |
net: don't let cancelation of a DNS lookup affect another lookup
Updates #8602
Updates #20703
Fixes #22724
Change-Id: I27b72311b2c66148c59977361bd3f5101e47b51d
Reviewed-on: https://go-review.googlesource.com/100840
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/lookup.go')
-rw-r--r-- | src/net/lookup.go | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/src/net/lookup.go b/src/net/lookup.go index 6844b1118f..dffbc016b2 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -194,10 +194,16 @@ func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, err resolverFunc = alt } + // We don't want a cancelation of ctx to affect the + // lookupGroup operation. Otherwise if our context gets + // canceled it might cause an error to be returned to a lookup + // using a completely different context. + lookupGroupCtx, lookupGroupCancel := context.WithCancel(context.Background()) + dnsWaitGroup.Add(1) ch, called := lookupGroup.DoChan(host, func() (interface{}, error) { defer dnsWaitGroup.Done() - return testHookLookupIP(ctx, resolverFunc, host) + return testHookLookupIP(lookupGroupCtx, resolverFunc, host) }) if !called { dnsWaitGroup.Done() @@ -205,20 +211,28 @@ func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, err select { case <-ctx.Done(): - // If the DNS lookup timed out for some reason, force - // future requests to start the DNS lookup again - // rather than waiting for the current lookup to - // complete. See issue 8602. - ctxErr := ctx.Err() - if ctxErr == context.DeadlineExceeded { - lookupGroup.Forget(host) + // Our context was canceled. If we are the only + // goroutine looking up this key, then drop the key + // from the lookupGroup and cancel the lookup. + // If there are other goroutines looking up this key, + // let the lookup continue uncanceled, and let later + // lookups with the same key share the result. + // See issues 8602, 20703, 22724. + if lookupGroup.ForgetUnshared(host) { + lookupGroupCancel() + } else { + go func() { + <-ch + lookupGroupCancel() + }() } - err := mapErr(ctxErr) + err := mapErr(ctx.Err()) if trace != nil && trace.DNSDone != nil { trace.DNSDone(nil, false, err) } return nil, err case r := <-ch: + lookupGroupCancel() if trace != nil && trace.DNSDone != nil { addrs, _ := r.Val.([]IPAddr) trace.DNSDone(ipAddrsEface(addrs), r.Shared, r.Err) |