-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: Client.Do returns different errors on context deadline depending on req/conn state #31863
Comments
I thought this was an interesting way to learn more about the go runtime, so I looked into it.
My next question was whether this was really a bug. Does it matter if the context is Done() Just to see whether this was some kind of new behavior, I tested on go versions all the way At this point i'm staring at runtime/netpoll.go and internal/poll/fd_poll_runtime.go, but I would I'm willing to look further in to this if it would be of help but first I'd like to hear from someone |
It sounds like the issue is that |
When I took a quick look, the problem was the one who did the dial saw the actual error and then it became a race between the deadline channel and the error propagation through layers of context as to what outcome each request sees. There is no easy way to fix this unless we have some well defined structure on how errors are propagated rather than creating go funcs that wait for 1 of many possible outcomes. |
Well, one approach (perhaps consistent with @ianlancetaylor's comment) is just to add a few lines to net/dial.go sysDial.dialSingle. Where it currently says:
Insert a check for the deadline being past due, and if so, wait on ctx.Done() as follows:
I tried this and built go. It passes my tests and the standard regression suite. |
I'm checking back in on this issue -- I'm happy to prepare a PR with my proposed fix and tests, but didn't want to move forward on it unless folks with a good understanding of the runtime thought such a PR was worth considering. |
There is a race between error propagation and closing a context's deadline channel. The result is that while the API that takes a context returns the correct error, context.Err() might return nil. See golang/go#31863 for more info.
* Use underlying error when checking for context errors There is a race between error propagation and closing a context's deadline channel. The result is that while the API that takes a context returns the correct error, context.Err() might return nil. See golang/go#31863 for more info. * further refinements * revert ordering of error check * add changelog entry
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Run multiple times program on my server (24 cpu)
https://play.golang.org/p/d00_wxKDN5f
With single goroutine - problem did not appears.
Problem appeared not every run, but in 3-4 runs at least one was faulty.
What did you expect to see?
all goroutines: done = true, err = Get http://240.0.0.1/test: context deadline exceeded
What did you see instead?
all gouroutines returned at the same time, after 4 seconds, like i specified in parent context.WithTimeout. But some goroutines returned before parentContext.Done was closed (error was i/o timeout), and some gorotines returned after parentCtx.Done was closed (with expected error "context deadline exceeded").
The text was updated successfully, but these errors were encountered: