http2: support concurrent Request.Close calls
While no guarantees are made about the safety of repeated or
concurrent closes of a request body, HTTP/1 request bodies are
concurrency-safe and HTTP/2 ones should be as well.
Fixes golang/go#51197
Change-Id: Id6527dc2932579cabc9cbe921c6e0b3b4a3d472c
Reviewed-on: https://go-review.googlesource.com/c/net/+/386495
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
diff --git a/http2/server.go b/http2/server.go
index 33765d3..b1c32eb 100644
--- a/http2/server.go
+++ b/http2/server.go
@@ -2316,17 +2316,18 @@
_ incomparable
stream *stream
conn *serverConn
- closed bool // for use by Close only
- sawEOF bool // for use by Read only
- pipe *pipe // non-nil if we have a HTTP entity message body
- needsContinue bool // need to send a 100-continue
+ closeOnce sync.Once // for use by Close only
+ sawEOF bool // for use by Read only
+ pipe *pipe // non-nil if we have a HTTP entity message body
+ needsContinue bool // need to send a 100-continue
}
func (b *requestBody) Close() error {
- if b.pipe != nil && !b.closed {
- b.pipe.BreakWithError(errClosedBody)
- }
- b.closed = true
+ b.closeOnce.Do(func() {
+ if b.pipe != nil {
+ b.pipe.BreakWithError(errClosedBody)
+ }
+ })
return nil
}