diff options
author | Maisem Ali <maisem@tailscale.com> | 2022-03-21 17:43:45 +0000 |
---|---|---|
committer | Heschi Kreinick <heschi@google.com> | 2022-05-09 20:17:13 +0000 |
commit | 4c5acd4b5729e3345a35ce43a8633d24dc1e42fc (patch) | |
tree | 5f70cbd59e929f01c6b74bb265adaf62af582474 /src/net/http/httptest/server_test.go | |
parent | 78992411ded8288ed32790ece2b998f0a6c7d997 (diff) | |
download | go-4c5acd4b5729e3345a35ce43a8633d24dc1e42fc.tar.gz go-4c5acd4b5729e3345a35ce43a8633d24dc1e42fc.zip |
[release-branch.go1.17] net/http/httptest: fix race in Server.Close
When run with race detector the test fails without the fix.
For #51799
Fixes #52455
Change-Id: I273adb6d3a2b1e0d606b9c27ab4c6a9aa4aa8064
GitHub-Last-Rev: a5ddd146a2a65f2e817eed5133449c79b3af2562
GitHub-Pull-Request: golang/go#51805
Reviewed-on: https://go-review.googlesource.com/c/go/+/393974
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 1d19cea740a5a044848aaab3dc119f60c947be1d)
Reviewed-on: https://go-review.googlesource.com/c/go/+/401318
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/net/http/httptest/server_test.go')
-rw-r--r-- | src/net/http/httptest/server_test.go | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/net/http/httptest/server_test.go b/src/net/http/httptest/server_test.go index 39568b358c..5313f65456 100644 --- a/src/net/http/httptest/server_test.go +++ b/src/net/http/httptest/server_test.go @@ -9,6 +9,7 @@ import ( "io" "net" "net/http" + "sync" "testing" ) @@ -203,6 +204,59 @@ func TestServerZeroValueClose(t *testing.T) { ts.Close() // tests that it doesn't panic } +// Issue 51799: test hijacking a connection and then closing it +// concurrently with closing the server. +func TestCloseHijackedConnection(t *testing.T) { + hijacked := make(chan net.Conn) + ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + defer close(hijacked) + hj, ok := w.(http.Hijacker) + if !ok { + t.Fatal("failed to hijack") + } + c, _, err := hj.Hijack() + if err != nil { + t.Fatal(err) + } + hijacked <- c + })) + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + req, err := http.NewRequest("GET", ts.URL, nil) + if err != nil { + t.Log(err) + } + // Use a client not associated with the Server. + var c http.Client + resp, err := c.Do(req) + if err != nil { + t.Log(err) + return + } + resp.Body.Close() + }() + + wg.Add(1) + conn := <-hijacked + go func(conn net.Conn) { + defer wg.Done() + // Close the connection and then inform the Server that + // we closed it. + conn.Close() + ts.Config.ConnState(conn, http.StateClosed) + }(conn) + + wg.Add(1) + go func() { + defer wg.Done() + ts.Close() + }() + wg.Wait() +} + func TestTLSServerWithHTTP2(t *testing.T) { modes := []struct { name string |