Skip to content

Commit 410d19e

Browse files
committed
http2: avoid racy access to clientStream.requestedGzip
clientStream.requestedGzip is set from clientStream.writeRequest, and examined by clientConn.readLoop. I'm not sure if there's any possible way for an actual data race to happen here in practice, since the read loop should only examine the field after the request is sent by writeRequest, but it's enough for the race detector to complain. Set the field in ClientConn.roundTrip instead, before the clientStream has become accessible to any other goroutines. No test, but a following CL has race detector failures without this change. Change-Id: Id30f1b95bcfcc35c213440e0e47cce3feaaff06d Reviewed-on: https://go-review.googlesource.com/c/net/+/586245 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Jonathan Amsterdam <jba@google.com>
1 parent 332fe23 commit 410d19e

File tree

2 files changed

+21
-20
lines changed

2 files changed

+21
-20
lines changed

http2/transport.go

+20-20
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,26 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream))
13011301
donec: make(chan struct{}),
13021302
}
13031303

1304+
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
1305+
if !cc.t.disableCompression() &&
1306+
req.Header.Get("Accept-Encoding") == "" &&
1307+
req.Header.Get("Range") == "" &&
1308+
!cs.isHead {
1309+
// Request gzip only, not deflate. Deflate is ambiguous and
1310+
// not as universally supported anyway.
1311+
// See: https://zlib.net/zlib_faq.html#faq39
1312+
//
1313+
// Note that we don't request this for HEAD requests,
1314+
// due to a bug in nginx:
1315+
// http://trac.nginx.org/nginx/ticket/358
1316+
// https://golang.org/issue/5522
1317+
//
1318+
// We don't request gzip if the request is for a range, since
1319+
// auto-decoding a portion of a gzipped document will just fail
1320+
// anyway. See https://golang.org/issue/8923
1321+
cs.requestedGzip = true
1322+
}
1323+
13041324
go cs.doRequest(req, streamf)
13051325

13061326
waitDone := func() error {
@@ -1449,26 +1469,6 @@ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStre
14491469
streamf(cs)
14501470
}
14511471

1452-
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
1453-
if !cc.t.disableCompression() &&
1454-
req.Header.Get("Accept-Encoding") == "" &&
1455-
req.Header.Get("Range") == "" &&
1456-
!cs.isHead {
1457-
// Request gzip only, not deflate. Deflate is ambiguous and
1458-
// not as universally supported anyway.
1459-
// See: https://zlib.net/zlib_faq.html#faq39
1460-
//
1461-
// Note that we don't request this for HEAD requests,
1462-
// due to a bug in nginx:
1463-
// http://trac.nginx.org/nginx/ticket/358
1464-
// https://golang.org/issue/5522
1465-
//
1466-
// We don't request gzip if the request is for a range, since
1467-
// auto-decoding a portion of a gzipped document will just fail
1468-
// anyway. See https://golang.org/issue/8923
1469-
cs.requestedGzip = true
1470-
}
1471-
14721472
continueTimeout := cc.t.expectContinueTimeout()
14731473
if continueTimeout != 0 {
14741474
if !httpguts.HeaderValuesContainsToken(req.Header["Expect"], "100-continue") {

http2/transport_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -2895,6 +2895,7 @@ func TestRoundTripDoesntConsumeRequestBodyEarly(t *testing.T) {
28952895
cc := &ClientConn{
28962896
closed: true,
28972897
reqHeaderMu: make(chan struct{}, 1),
2898+
t: &Transport{},
28982899
}
28992900
_, err := cc.RoundTrip(req)
29002901
if err != errClientConnUnusable {

0 commit comments

Comments
 (0)