Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2455)

Delta Between Two Patch Sets: src/net/lookup.go

Issue 154610044: code review 154610044: net: if a DNS lookup times out, forget that it is in flight (Closed)
Left Patch Set: Created 9 years, 5 months ago
Right Patch Set: diff -r 207a56999953fec99622802b5002cc65c7a2f833 https://code.google.com/p/go Created 9 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/net/singleflight.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package net 5 package net
6 6
7 import "time" 7 import "time"
8 8
9 // protocols contains minimal mappings between internet protocol 9 // protocols contains minimal mappings between internet protocol
10 // names and numbers for platforms that don't have a complete list of 10 // names and numbers for platforms that don't have a complete list of
(...skipping 22 matching lines...) Expand all
33 33
34 var lookupGroup singleflight 34 var lookupGroup singleflight
35 35
36 // lookupIPMerge wraps lookupIP, but makes sure that for any given 36 // lookupIPMerge wraps lookupIP, but makes sure that for any given
37 // host, only one lookup is in-flight at a time. The returned memory 37 // host, only one lookup is in-flight at a time. The returned memory
38 // is always owned by the caller. 38 // is always owned by the caller.
39 func lookupIPMerge(host string) (addrs []IP, err error) { 39 func lookupIPMerge(host string) (addrs []IP, err error) {
40 addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) { 40 addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
41 return lookupIP(host) 41 return lookupIP(host)
42 }) 42 })
43 return lookupIPReturn(addrsi, err, shared)
44 }
45
46 // lookupIPReturn turns the return values from singleflight.Do into
47 // the return values from LookupIP.
48 func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IP, error) {
43 if err != nil { 49 if err != nil {
44 return nil, err 50 return nil, err
45 } 51 }
46 » addrs = addrsi.([]IP) 52 » addrs := addrsi.([]IP)
47 if shared { 53 if shared {
48 clone := make([]IP, len(addrs)) 54 clone := make([]IP, len(addrs))
49 copy(clone, addrs) 55 copy(clone, addrs)
50 addrs = clone 56 addrs = clone
51 } 57 }
52 return addrs, nil 58 return addrs, nil
53 } 59 }
54 60
61 // lookupIPDeadline looks up a hostname with a deadline.
55 func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) { 62 func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) {
56 if deadline.IsZero() { 63 if deadline.IsZero() {
57 return lookupIPMerge(host) 64 return lookupIPMerge(host)
58 } 65 }
59 66
60 » // TODO(bradfitz): consider pushing the deadline down into the 67 » // We could push the deadline down into the name resolution
61 » // name resolution functions. But that involves fixing it for 68 » // functions. However, the most commonly used implementation
62 » // the native Go resolver, cgo, Windows, etc. 69 » // calls getaddrinfo, which has no timeout.
63 » // 70
64 » // In the meantime, just use a goroutine. Most users affected
65 » // by http://golang.org/issue/2631 are due to TCP connections
66 » // to unresponsive hosts, not DNS.
67 timeout := deadline.Sub(time.Now()) 71 timeout := deadline.Sub(time.Now())
68 if timeout <= 0 { 72 if timeout <= 0 {
69 » » err = errTimeout 73 » » return nil, errTimeout
70 » » return
71 } 74 }
72 t := time.NewTimer(timeout) 75 t := time.NewTimer(timeout)
73 defer t.Stop() 76 defer t.Stop()
74 » type res struct { 77
75 » » addrs []IP 78 » ch := lookupGroup.DoChan(host, func() (interface{}, error) {
76 » » err error 79 » » return lookupIP(host)
77 » } 80 » })
78 » resc := make(chan res, 1) 81
79 » go func() {
80 » » a, err := lookupIPMerge(host)
81 » » resc <- res{a, err}
82 » }()
83 select { 82 select {
84 case <-t.C: 83 case <-t.C:
85 » » err = errTimeout 84 » » // The DNS lookup timed out for some reason. Force
86 » case r := <-resc: 85 » » // future requests to start the DNS lookup again
87 » » addrs, err = r.addrs, r.err 86 » » // rather than waiting for the current lookup to
87 » » // complete. See issue 8602.
88 » » lookupGroup.Forget(host)
89
90 » » return nil, errTimeout
91
92 » case r := <-ch:
93 » » return lookupIPReturn(r.v, r.err, r.shared)
88 } 94 }
89 return
90 } 95 }
91 96
92 // LookupPort looks up the port for the given network and service. 97 // LookupPort looks up the port for the given network and service.
93 func LookupPort(network, service string) (port int, err error) { 98 func LookupPort(network, service string) (port int, err error) {
94 return lookupPort(network, service) 99 return lookupPort(network, service)
95 } 100 }
96 101
97 // LookupCNAME returns the canonical DNS host for the given name. 102 // LookupCNAME returns the canonical DNS host for the given name.
98 // Callers that do not care about the canonical name can call 103 // Callers that do not care about the canonical name can call
99 // LookupHost or LookupIP directly; both take care of resolving 104 // LookupHost or LookupIP directly; both take care of resolving
(...skipping 28 matching lines...) Expand all
128 // LookupTXT returns the DNS TXT records for the given domain name. 133 // LookupTXT returns the DNS TXT records for the given domain name.
129 func LookupTXT(name string) (txt []string, err error) { 134 func LookupTXT(name string) (txt []string, err error) {
130 return lookupTXT(name) 135 return lookupTXT(name)
131 } 136 }
132 137
133 // LookupAddr performs a reverse lookup for the given address, returning a list 138 // LookupAddr performs a reverse lookup for the given address, returning a list
134 // of names mapping to that address. 139 // of names mapping to that address.
135 func LookupAddr(addr string) (name []string, err error) { 140 func LookupAddr(addr string) (name []string, err error) {
136 return lookupAddr(addr) 141 return lookupAddr(addr)
137 } 142 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b