mirror of https://github.com/golang/go.git
[dev.link] all: merge branch 'master' into dev.link
Clean merge. Change-Id: If642f7901a797c6df5a0fa64aecebba22e5ee951
This commit is contained in:
commit
d9c19a7d3e
|
|
@ -655,8 +655,8 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 221427 -->
|
||||
When the flag package sees <code>-h</code> or <code>-help</code>, and
|
||||
those flags are not defined, it now prints a usage message.
|
||||
When the <code>flag</code> package sees <code>-h</code> or <code>-help</code>,
|
||||
and those flags are not defined, it now prints a usage message.
|
||||
If the <a href="/pkg/flag/#FlagSet"><code>FlagSet</code></a> was created with
|
||||
<a href="/pkg/flag/#ExitOnError"><code>ExitOnError</code></a>,
|
||||
<a href="/pkg/flag/#FlagSet.Parse"><code>FlagSet.Parse</code></a> would then
|
||||
|
|
@ -901,9 +901,9 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<dl id="pkg-runtime-pprof"><dt><a href="/pkg/runtime/pprof/">runtime/pprof</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 189318 -->
|
||||
The goroutine profile includes the profile labels associated with each goroutine
|
||||
at the time of profiling. This feature is not yet implemented for the profile
|
||||
reported with <code>debug=2</code>.
|
||||
The goroutine profile now includes the profile labels associated with each
|
||||
goroutine at the time of profiling. This feature is not yet implemented for
|
||||
the profile reported with <code>debug=2</code>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
@ -934,6 +934,7 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<a href="/pkg/sync/#Map.Delete"><code>Map.Delete</code></a>
|
||||
is more efficient.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- sync -->
|
||||
|
||||
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ require (
|
|||
golang.org/x/mod v0.3.0
|
||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect
|
||||
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054
|
||||
golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,4 +34,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
|||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316 h1:Jhw4VC65LaKnpq9FvcK+a8ZzrFm3D+UygvMMrhkOw70=
|
||||
golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
|
|
|||
|
|
@ -239,11 +239,25 @@ func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportSta
|
|||
err = &NoGoError{Package: p}
|
||||
}
|
||||
|
||||
// Take only the first error from a scanner.ErrorList. PackageError only
|
||||
// has room for one position, so we report the first error with a position
|
||||
// instead of all of the errors without a position.
|
||||
var pos string
|
||||
var isScanErr bool
|
||||
if scanErr, ok := err.(scanner.ErrorList); ok && len(scanErr) > 0 {
|
||||
isScanErr = true // For stack push/pop below.
|
||||
|
||||
scanPos := scanErr[0].Pos
|
||||
scanPos.Filename = base.ShortPath(scanPos.Filename)
|
||||
pos = scanPos.String()
|
||||
err = errors.New(scanErr[0].Msg)
|
||||
}
|
||||
|
||||
// Report the error on the importing package if the problem is with the import declaration
|
||||
// for example, if the package doesn't exist or if the import path is malformed.
|
||||
// On the other hand, don't include a position if the problem is with the imported package,
|
||||
// for example there are no Go files (NoGoError), or there's a problem in the imported
|
||||
// package's source files themselves.
|
||||
// package's source files themselves (scanner errors).
|
||||
//
|
||||
// TODO(matloob): Perhaps make each of those the errors in the first group
|
||||
// (including modload.ImportMissingError, and the corresponding
|
||||
|
|
@ -254,22 +268,11 @@ func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportSta
|
|||
// to make it easier to check for them? That would save us from having to
|
||||
// move the modload errors into this package to avoid a package import cycle,
|
||||
// and from having to export an error type for the errors produced in build.
|
||||
if !isMatchErr && nogoErr != nil {
|
||||
if !isMatchErr && (nogoErr != nil || isScanErr) {
|
||||
stk.Push(path)
|
||||
defer stk.Pop()
|
||||
}
|
||||
|
||||
// Take only the first error from a scanner.ErrorList. PackageError only
|
||||
// has room for one position, so we report the first error with a position
|
||||
// instead of all of the errors without a position.
|
||||
var pos string
|
||||
if scanErr, ok := err.(scanner.ErrorList); ok && len(scanErr) > 0 {
|
||||
scanPos := scanErr[0].Pos
|
||||
scanPos.Filename = base.ShortPath(scanPos.Filename)
|
||||
pos = scanPos.String()
|
||||
err = errors.New(scanErr[0].Msg)
|
||||
}
|
||||
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Pos: pos,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
# golang.org/issue/40544: regression in error stacks for parse errors
|
||||
|
||||
env GO111MODULE=off
|
||||
cd sandbox/foo
|
||||
go list -e -json .
|
||||
stdout '"sandbox/foo"'
|
||||
stdout '"sandbox/bar"'
|
||||
stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
|
||||
stdout '"Err": "expected ''package'', found ackage"'
|
||||
|
||||
env GO111MODULE=on
|
||||
go list -e -json .
|
||||
stdout '"sandbox/foo"'
|
||||
stdout '"sandbox/bar"'
|
||||
stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
|
||||
stdout '"Err": "expected ''package'', found ackage"'
|
||||
|
||||
-- sandbox/go.mod --
|
||||
module sandbox
|
||||
|
||||
-- sandbox/foo/foo.go --
|
||||
package pkg
|
||||
|
||||
import "sandbox/bar"
|
||||
-- sandbox/bar/bar.go --
|
||||
ackage bar
|
||||
|
|
@ -84,6 +84,7 @@ golang.org/x/tools/go/cfg
|
|||
golang.org/x/tools/go/types/objectpath
|
||||
golang.org/x/tools/go/types/typeutil
|
||||
golang.org/x/tools/internal/analysisinternal
|
||||
# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
|
||||
# golang.org/x/xerrors v0.0.0-20200806184451-1a77d5e9f316
|
||||
## explicit
|
||||
golang.org/x/xerrors
|
||||
golang.org/x/xerrors/internal
|
||||
|
|
|
|||
|
|
@ -106,13 +106,13 @@ var overflow = errors.New("binary: varint overflows a 64-bit integer")
|
|||
func ReadUvarint(r io.ByteReader) (uint64, error) {
|
||||
var x uint64
|
||||
var s uint
|
||||
for i := 0; ; i++ {
|
||||
for i := 0; i < MaxVarintLen64; i++ {
|
||||
b, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return x, err
|
||||
}
|
||||
if b < 0x80 {
|
||||
if i > 9 || i == 9 && b > 1 {
|
||||
if i == 9 && b > 1 {
|
||||
return x, overflow
|
||||
}
|
||||
return x | uint64(b)<<s, nil
|
||||
|
|
@ -120,6 +120,7 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
|
|||
x |= uint64(b&0x7f) << s
|
||||
s += 7
|
||||
}
|
||||
return x, overflow
|
||||
}
|
||||
|
||||
// ReadVarint reads an encoded signed integer from r and returns it as an int64.
|
||||
|
|
|
|||
|
|
@ -121,21 +121,27 @@ func TestBufferTooSmall(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func testOverflow(t *testing.T, buf []byte, n0 int, err0 error) {
|
||||
func testOverflow(t *testing.T, buf []byte, x0 uint64, n0 int, err0 error) {
|
||||
x, n := Uvarint(buf)
|
||||
if x != 0 || n != n0 {
|
||||
t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
|
||||
}
|
||||
|
||||
x, err := ReadUvarint(bytes.NewReader(buf))
|
||||
if x != 0 || err != err0 {
|
||||
t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want 0, %s", buf, x, err, err0)
|
||||
r := bytes.NewReader(buf)
|
||||
len := r.Len()
|
||||
x, err := ReadUvarint(r)
|
||||
if x != x0 || err != err0 {
|
||||
t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want %d, %s", buf, x, err, x0, err0)
|
||||
}
|
||||
if read := len - r.Len(); read > MaxVarintLen64 {
|
||||
t.Errorf("ReadUvarint(%v): read more than MaxVarintLen64 bytes, got %d", buf, read)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverflow(t *testing.T) {
|
||||
testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, -10, overflow)
|
||||
testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, -13, overflow)
|
||||
testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, 0, -10, overflow)
|
||||
testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -13, overflow)
|
||||
testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, 0, overflow) // 11 bytes, should overflow
|
||||
}
|
||||
|
||||
func TestNonCanonicalZero(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ type Transport struct {
|
|||
idleLRU connLRU
|
||||
|
||||
reqMu sync.Mutex
|
||||
reqCanceler map[*Request]func(error)
|
||||
reqCanceler map[cancelKey]func(error)
|
||||
|
||||
altMu sync.Mutex // guards changing altProto only
|
||||
altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme
|
||||
|
|
@ -273,6 +273,13 @@ type Transport struct {
|
|||
ForceAttemptHTTP2 bool
|
||||
}
|
||||
|
||||
// A cancelKey is the key of the reqCanceler map.
|
||||
// We wrap the *Request in this type since we want to use the original request,
|
||||
// not any transient one created by roundTrip.
|
||||
type cancelKey struct {
|
||||
req *Request
|
||||
}
|
||||
|
||||
func (t *Transport) writeBufferSize() int {
|
||||
if t.WriteBufferSize > 0 {
|
||||
return t.WriteBufferSize
|
||||
|
|
@ -433,9 +440,10 @@ func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) {
|
|||
// optional extra headers to write and stores any error to return
|
||||
// from roundTrip.
|
||||
type transportRequest struct {
|
||||
*Request // original request, not to be mutated
|
||||
extra Header // extra headers to write, or nil
|
||||
trace *httptrace.ClientTrace // optional
|
||||
*Request // original request, not to be mutated
|
||||
extra Header // extra headers to write, or nil
|
||||
trace *httptrace.ClientTrace // optional
|
||||
cancelKey cancelKey
|
||||
|
||||
mu sync.Mutex // guards err
|
||||
err error // first setError value for mapRoundTripError to consider
|
||||
|
|
@ -512,6 +520,7 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
|
|||
}
|
||||
|
||||
origReq := req
|
||||
cancelKey := cancelKey{origReq}
|
||||
req = setupRewindBody(req)
|
||||
|
||||
if altRT := t.alternateRoundTripper(req); altRT != nil {
|
||||
|
|
@ -546,7 +555,7 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
|
|||
}
|
||||
|
||||
// treq gets modified by roundTrip, so we need to recreate for each retry.
|
||||
treq := &transportRequest{Request: req, trace: trace}
|
||||
treq := &transportRequest{Request: req, trace: trace, cancelKey: cancelKey}
|
||||
cm, err := t.connectMethodForRequest(treq)
|
||||
if err != nil {
|
||||
req.closeBody()
|
||||
|
|
@ -559,7 +568,7 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
|
|||
// to send it requests.
|
||||
pconn, err := t.getConn(treq, cm)
|
||||
if err != nil {
|
||||
t.setReqCanceler(req, nil)
|
||||
t.setReqCanceler(cancelKey, nil)
|
||||
req.closeBody()
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -567,7 +576,7 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
|
|||
var resp *Response
|
||||
if pconn.alt != nil {
|
||||
// HTTP/2 path.
|
||||
t.setReqCanceler(req, nil) // not cancelable with CancelRequest
|
||||
t.setReqCanceler(cancelKey, nil) // not cancelable with CancelRequest
|
||||
resp, err = pconn.alt.RoundTrip(req)
|
||||
} else {
|
||||
resp, err = pconn.roundTrip(treq)
|
||||
|
|
@ -753,14 +762,14 @@ func (t *Transport) CloseIdleConnections() {
|
|||
// cancelable context instead. CancelRequest cannot cancel HTTP/2
|
||||
// requests.
|
||||
func (t *Transport) CancelRequest(req *Request) {
|
||||
t.cancelRequest(req, errRequestCanceled)
|
||||
t.cancelRequest(cancelKey{req}, errRequestCanceled)
|
||||
}
|
||||
|
||||
// Cancel an in-flight request, recording the error value.
|
||||
func (t *Transport) cancelRequest(req *Request, err error) {
|
||||
func (t *Transport) cancelRequest(key cancelKey, err error) {
|
||||
t.reqMu.Lock()
|
||||
cancel := t.reqCanceler[req]
|
||||
delete(t.reqCanceler, req)
|
||||
cancel := t.reqCanceler[key]
|
||||
delete(t.reqCanceler, key)
|
||||
t.reqMu.Unlock()
|
||||
if cancel != nil {
|
||||
cancel(err)
|
||||
|
|
@ -1093,16 +1102,16 @@ func (t *Transport) removeIdleConnLocked(pconn *persistConn) bool {
|
|||
return removed
|
||||
}
|
||||
|
||||
func (t *Transport) setReqCanceler(r *Request, fn func(error)) {
|
||||
func (t *Transport) setReqCanceler(key cancelKey, fn func(error)) {
|
||||
t.reqMu.Lock()
|
||||
defer t.reqMu.Unlock()
|
||||
if t.reqCanceler == nil {
|
||||
t.reqCanceler = make(map[*Request]func(error))
|
||||
t.reqCanceler = make(map[cancelKey]func(error))
|
||||
}
|
||||
if fn != nil {
|
||||
t.reqCanceler[r] = fn
|
||||
t.reqCanceler[key] = fn
|
||||
} else {
|
||||
delete(t.reqCanceler, r)
|
||||
delete(t.reqCanceler, key)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1110,17 +1119,17 @@ func (t *Transport) setReqCanceler(r *Request, fn func(error)) {
|
|||
// for the request, we don't set the function and return false.
|
||||
// Since CancelRequest will clear the canceler, we can use the return value to detect if
|
||||
// the request was canceled since the last setReqCancel call.
|
||||
func (t *Transport) replaceReqCanceler(r *Request, fn func(error)) bool {
|
||||
func (t *Transport) replaceReqCanceler(key cancelKey, fn func(error)) bool {
|
||||
t.reqMu.Lock()
|
||||
defer t.reqMu.Unlock()
|
||||
_, ok := t.reqCanceler[r]
|
||||
_, ok := t.reqCanceler[key]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if fn != nil {
|
||||
t.reqCanceler[r] = fn
|
||||
t.reqCanceler[key] = fn
|
||||
} else {
|
||||
delete(t.reqCanceler, r)
|
||||
delete(t.reqCanceler, key)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
@ -1324,12 +1333,12 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (pc *persi
|
|||
// set request canceler to some non-nil function so we
|
||||
// can detect whether it was cleared between now and when
|
||||
// we enter roundTrip
|
||||
t.setReqCanceler(req, func(error) {})
|
||||
t.setReqCanceler(treq.cancelKey, func(error) {})
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
cancelc := make(chan error, 1)
|
||||
t.setReqCanceler(req, func(err error) { cancelc <- err })
|
||||
t.setReqCanceler(treq.cancelKey, func(err error) { cancelc <- err })
|
||||
|
||||
// Queue for permission to dial.
|
||||
t.queueForDial(w)
|
||||
|
|
@ -2078,7 +2087,7 @@ func (pc *persistConn) readLoop() {
|
|||
}
|
||||
|
||||
if !hasBody || bodyWritable {
|
||||
pc.t.setReqCanceler(rc.req, nil)
|
||||
pc.t.setReqCanceler(rc.cancelKey, nil)
|
||||
|
||||
// Put the idle conn back into the pool before we send the response
|
||||
// so if they process it quickly and make another request, they'll
|
||||
|
|
@ -2151,7 +2160,7 @@ func (pc *persistConn) readLoop() {
|
|||
// reading the response body. (or for cancellation or death)
|
||||
select {
|
||||
case bodyEOF := <-waitForBodyRead:
|
||||
pc.t.setReqCanceler(rc.req, nil) // before pc might return to idle pool
|
||||
pc.t.setReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool
|
||||
alive = alive &&
|
||||
bodyEOF &&
|
||||
!pc.sawEOF &&
|
||||
|
|
@ -2165,7 +2174,7 @@ func (pc *persistConn) readLoop() {
|
|||
pc.t.CancelRequest(rc.req)
|
||||
case <-rc.req.Context().Done():
|
||||
alive = false
|
||||
pc.t.cancelRequest(rc.req, rc.req.Context().Err())
|
||||
pc.t.cancelRequest(rc.cancelKey, rc.req.Context().Err())
|
||||
case <-pc.closech:
|
||||
alive = false
|
||||
}
|
||||
|
|
@ -2408,9 +2417,10 @@ type responseAndError struct {
|
|||
}
|
||||
|
||||
type requestAndChan struct {
|
||||
_ incomparable
|
||||
req *Request
|
||||
ch chan responseAndError // unbuffered; always send in select on callerGone
|
||||
_ incomparable
|
||||
req *Request
|
||||
cancelKey cancelKey
|
||||
ch chan responseAndError // unbuffered; always send in select on callerGone
|
||||
|
||||
// whether the Transport (as opposed to the user client code)
|
||||
// added the Accept-Encoding gzip header. If the Transport
|
||||
|
|
@ -2472,7 +2482,7 @@ var (
|
|||
|
||||
func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
|
||||
testHookEnterRoundTrip()
|
||||
if !pc.t.replaceReqCanceler(req.Request, pc.cancelRequest) {
|
||||
if !pc.t.replaceReqCanceler(req.cancelKey, pc.cancelRequest) {
|
||||
pc.t.putOrCloseIdleConn(pc)
|
||||
return nil, errRequestCanceled
|
||||
}
|
||||
|
|
@ -2524,7 +2534,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
|
|||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
pc.t.setReqCanceler(req.Request, nil)
|
||||
pc.t.setReqCanceler(req.cancelKey, nil)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
@ -2540,6 +2550,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
|
|||
resc := make(chan responseAndError)
|
||||
pc.reqch <- requestAndChan{
|
||||
req: req.Request,
|
||||
cancelKey: req.cancelKey,
|
||||
ch: resc,
|
||||
addedGzip: requestedGzip,
|
||||
continueCh: continueCh,
|
||||
|
|
@ -2591,10 +2602,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
|
|||
}
|
||||
return re.res, nil
|
||||
case <-cancelChan:
|
||||
pc.t.CancelRequest(req.Request)
|
||||
pc.t.cancelRequest(req.cancelKey, errRequestCanceled)
|
||||
cancelChan = nil
|
||||
case <-ctxDoneChan:
|
||||
pc.t.cancelRequest(req.Request, req.Context().Err())
|
||||
pc.t.cancelRequest(req.cancelKey, req.Context().Err())
|
||||
cancelChan = nil
|
||||
ctxDoneChan = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2364,6 +2364,50 @@ func TestTransportCancelRequest(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func testTransportCancelRequestInDo(t *testing.T, body io.Reader) {
|
||||
setParallel(t)
|
||||
defer afterTest(t)
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in -short mode")
|
||||
}
|
||||
unblockc := make(chan bool)
|
||||
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||
<-unblockc
|
||||
}))
|
||||
defer ts.Close()
|
||||
defer close(unblockc)
|
||||
|
||||
c := ts.Client()
|
||||
tr := c.Transport.(*Transport)
|
||||
|
||||
donec := make(chan bool)
|
||||
req, _ := NewRequest("GET", ts.URL, body)
|
||||
go func() {
|
||||
defer close(donec)
|
||||
c.Do(req)
|
||||
}()
|
||||
start := time.Now()
|
||||
timeout := 10 * time.Second
|
||||
for time.Since(start) < timeout {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
tr.CancelRequest(req)
|
||||
select {
|
||||
case <-donec:
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
t.Errorf("Do of canceled request has not returned after %v", timeout)
|
||||
}
|
||||
|
||||
func TestTransportCancelRequestInDo(t *testing.T) {
|
||||
testTransportCancelRequestInDo(t, nil)
|
||||
}
|
||||
|
||||
func TestTransportCancelRequestWithBodyInDo(t *testing.T) {
|
||||
testTransportCancelRequestInDo(t, bytes.NewBuffer([]byte{0}))
|
||||
}
|
||||
|
||||
func TestTransportCancelRequestInDial(t *testing.T) {
|
||||
defer afterTest(t)
|
||||
if testing.Short() {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ To update the .syso files use golang.org/x/build/cmd/racebuild.
|
|||
|
||||
race_darwin_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
|
||||
race_freebsd_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
|
||||
race_linux_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
|
||||
race_linux_ppc64le.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
|
||||
race_linux_amd64.syso built with LLVM 6c75db8b4bc59eace18143ce086419d37da24746 and Go 7388956b76ce15a11346cebefcf6193db044caaf.
|
||||
race_linux_ppc64le.syso built with LLVM 6c75db8b4bc59eace18143ce086419d37da24746 and Go 7388956b76ce15a11346cebefcf6193db044caaf.
|
||||
race_netbsd_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
|
||||
race_windows_amd64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
|
||||
race_linux_arm64.syso built with LLVM 3496d6e4bea9cb99cb382939b7e79a50a3b863a5 and Go 553e003414d3aa90cc39830ee22f08453d9f3408.
|
||||
race_linux_arm64.syso built with LLVM 6c75db8b4bc59eace18143ce086419d37da24746 and Go 7388956b76ce15a11346cebefcf6193db044caaf.
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !android,!js,!ppc64le
|
||||
|
||||
// Note: we don't run on Android or ppc64 because if there is any non-race test
|
||||
// file in this package, the OS tries to link the .syso file into the
|
||||
// test (even when we're not in race mode), which fails. I'm not sure
|
||||
// why, but easiest to just punt - as long as a single builder runs
|
||||
// this test, we're good.
|
||||
|
||||
package race
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIssue37485(t *testing.T) {
|
||||
files, err := filepath.Glob("./*.syso")
|
||||
if err != nil {
|
||||
t.Fatalf("can't find syso files: %s", err)
|
||||
}
|
||||
for _, f := range files {
|
||||
cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), "tool", "nm", f)
|
||||
res, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("nm of %s failed: %s", f, err)
|
||||
continue
|
||||
}
|
||||
if bytes.Contains(res, []byte("getauxval")) {
|
||||
t.Errorf("%s contains getauxval", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue