Closed
Description
The implementation of http.Transport.CancelRequest looks for the supplied request struct in a map of in-flight requests, doing nothing if it doesn't exist. If I understand correctly, that means that this snippet is racy, in the sense that cancellation of the context may be lost if it is seen before RoundTrip gets around to sticking the request in the map:
func cancellableDo(ctx context.Context, req *http.Request) (err error) {
// Propagate cancellation of the context to the HTTP request.
go func() {
<-context.Done()
http.DefaultTransport.CancelRequest(req)
}()
// Call through.
err = http.DefaultTransport.RoundTrip(req)
return
}
This is made more likely to happen by RoundTripper implementations like oauth2.Transport, which may make network calls before calling through to RoundTrip. In the end I'm forced to cancel in a hacky loop to ensure that the HTTP package pays attention.
Is there anything that can be done to eliminate this race?