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
x/net/context/ctxhttp: remove racy go1.4 support #13293
Comments
It's quite probable that ctxhttp is racy in Go 1.4. There isn't a way to do it in a non-racy way for Go 1.4, though (that's why the net/http API changed in Go 1.5). |
@pwaller would that approach work if there was no request body? The 1.4 support is racy, yes. I'm not too inclined to invest in fixing it though since a correct solution is going to increase complexity dramatically for little benefit. |
@okdave, I understand that it works if there is no request body, yes. The body is written as part of I'd like to see this fixed this because it means leaking connections and goroutines to docker in go-dockerclient, which a long lived process of mine uses. I want to implement cancellation in go-dockerclient in terms of ctxhttp but don't feel comfortable doing so while I know there is some chance that connections are leaked if someone is unlucky enough to build with go 1.4. The presence of this leak makes it harder to identify and diagnose other leaks. The failure I'm concerned about is particularly pathological because the other side (docker) of the connection will hold the connection open indefinitely in some cases, so it could quickly run out of file descriptors and leak an unreasonable number of goroutines. By avoiding the complexity in the library, that is pushing it onto the users! :) |
By the way, I just ran the ctxhttp tests under go1.4 with this tweak: func canceler(client *http.Client, req *http.Request) func() {
rc, ok := client.Transport.(requestCanceler)
if !ok {
return func() {
log.Printf("Not a canceler: %T", client.Transport)
}
}
return func() {
log.Printf("Using 1.4 canceler")
rc.CancelRequest(req)
}
} The output is this:
This would appear to indicate that the tests aren't exercising the canceller on go1.4, and possibly the canceller is having no effect anyway? (Also I hit this already fixed race in case anyone happens on it during investigation) |
I have opened #13325 for the above question of @okdave to avoid confusing this issue, which is about the go1.4 code being racy before the request is in flight. (Aside: So now we have a problem where the request can't be cancelled before, and it can't be cancelled after, which means there is only a very "narrow" window — during the exchange of headers — where cancellation does anything. If that's ctxhttp working as intended, the documentation needs to be improved.) |
Note: I ended up not using this for my original use case, so I'm unlikely to follow this up. I don't suppose anyone else is either, since 1.4 is soon to be two major versions behind and few people are likely to hit this. I would be OK with closing this issue. |
We may as well leave this open to actually drop the Go 1.4 support soon. |
It's been removed. |
x/net/context/ctxhttp has code specifically to handle go1.4, and I believe this code is racy.
Details of this style of race: #11013
No synchronization here...
...Against the request going in flight.
Example of the sort of thing I understand that needs to be done with the 1.4 cancellation interface (I wrote this with Bradfitz' input, which is when I became aware of the issue).
The problem is the definition of the canceller API in Go1.4 - cancelling the request is only a valid thing to do once the request is in flight, otherwise the cancellation is ignored. Hence the need for the req.Body acrobatics in reverseproxy, and hence the improved API in 1.5.
golang-dev discussion.
The text was updated successfully, but these errors were encountered: