aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/httputil/reverseproxy.go
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2018-10-09 16:01:20 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2018-10-10 02:08:36 +0000
commitc870d56f98eab5370726afd223fe0ab14d9e88ab (patch)
tree090011f3cc0598e48818311c36fba465d47b99e5 /src/net/http/httputil/reverseproxy.go
parent95d06ab6c982f58b127b14a52c3325acf0bd3926 (diff)
downloadgo-c870d56f98eab5370726afd223fe0ab14d9e88ab.tar.gz
go-c870d56f98eab5370726afd223fe0ab14d9e88ab.zip
net/http/httputil: fix race/crash in previous ReverseProxy change
The previous ReverseProxy change, CL 137335, introduced a bug which could cause a race and/or a crash. This reliably crashed before: $ go test -short -race -v -run=TestReverseProxyFlushInterval -count=20 net/http/httputil The problem was a goroutine was running http.ResponseWriter.Flush after the http.Handler's ServeHTTP completed. There was code to prevent that (a deferred stop call) but the stop call didn't consider the case where time.AfterFunc had already fired off a new goroutine but that goroutine hadn't yet scheduled. Change-Id: I06357908465a3b953efc33e63c70dec19a501adf Reviewed-on: https://go-review.googlesource.com/c/140977 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Diffstat (limited to 'src/net/http/httputil/reverseproxy.go')
-rw-r--r--src/net/http/httputil/reverseproxy.go4
1 files changed, 4 insertions, 0 deletions
diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index 1efcbd3bbc..f82d820a43 100644
--- a/src/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -448,6 +448,9 @@ func (m *maxLatencyWriter) Write(p []byte) (n int, err error) {
func (m *maxLatencyWriter) delayedFlush() {
m.mu.Lock()
defer m.mu.Unlock()
+ if !m.flushPending { // if stop was called but AfterFunc already started this goroutine
+ return
+ }
m.dst.Flush()
m.flushPending = false
}
@@ -455,6 +458,7 @@ func (m *maxLatencyWriter) delayedFlush() {
func (m *maxLatencyWriter) stop() {
m.mu.Lock()
defer m.mu.Unlock()
+ m.flushPending = false
if m.t != nil {
m.t.Stop()
}