-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Open
Labels
BugReportIssues describing a possible bug in the Go implementation.Issues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone
Description
Go version
go version go1.23.2 darwin/arm64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/zy.chen/Library/Caches/go-build'
GOENV='/Users/zy.chen/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/zy.chen/go/pkg/mod'
GONOPROXY='github.com/AfterShip'
GONOSUMDB='github.com/AfterShip'
GOOS='darwin'
GOPATH='/Users/zy.chen/go'
GOPRIVATE='github.com/AfterShip'
GOPROXY='direct'
GOROOT='/opt/homebrew/Cellar/go/1.23.2/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.23.2/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.2'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/zy.chen/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/opt/homebrew/opt/go/libexec/src/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/fm/spjh4bvs1hzfsg9w8ybmc1zm0000gn/T/go-build2972010941=/tmp/go-build -gno-record-gcc-switches -fno-common'
What did you do?
Found an inconsistency in error message in net/http/client.go
.
What did you see happen?
The current error message says:
if b.reqDidTimeout() {
err = &timeoutError{err.Error() + " (Client.Timeout or context cancellation while reading body)"}
}
However, when reqDidTimeout() returns true in cancelTimerBody.Read(), it should only be due to Client.Timeout expiration, so the error message should only mention "Client.Timeout".
What did you expect to see?
The error message should only mention "Client.Timeout" as below:
err = &timeoutError{err.Error() + " (Client.Timeout exceeded while reading body)"}
Analysis
After analyzing the code in setRequestCancel()
, reqDidTimeout()
only returns true when:
- fast path: return true when client timeout exceeds
if req.Cancel == nil && knownTransport {
// If they already had a Request.Context that's
// expiring sooner, do nothing:
if !timeBeforeContextDeadline(deadline, oldCtx) {
return nop, alwaysFalse
}
var cancelCtx func()
req.ctx, cancelCtx = context.WithDeadline(oldCtx, deadline)
return cancelCtx, func() bool { return time.Now().After(deadline) }
}
- normal path: return true when the timer created with deadline fires
(<-timer.C)
timer := time.NewTimer(time.Until(deadline))
var timedOut atomic.Bool
go func() {
select {
case <-initialReqCancel:
doCancel()
timer.Stop()
case <-timer.C:
timedOut.Store(true)
doCancel()
case <-stopTimerCh:
timer.Stop()
}
}()
return stopTimer, timedOut.Load
Context cancellation or timeout does not trigger timedOut.Store(true)
, so when reqDidTimeout()
returns true, it's always due to client timeout.
Metadata
Metadata
Assignees
Labels
BugReportIssues describing a possible bug in the Go implementation.Issues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.