From b3976111ae1d3bbbfa36045f99acce7911a18c44 Mon Sep 17 00:00:00 2001 From: Hilko Bengen Date: Thu, 3 Dec 2020 02:03:01 +0100 Subject: [PATCH] net/http/fcgi: Add test demonstrating race condition --- src/net/http/fcgi/fcgi_test.go | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/net/http/fcgi/fcgi_test.go b/src/net/http/fcgi/fcgi_test.go index d3b704f8219..86514b6d4cd 100644 --- a/src/net/http/fcgi/fcgi_test.go +++ b/src/net/http/fcgi/fcgi_test.go @@ -11,6 +11,7 @@ import ( "net/http" "strings" "testing" + "time" ) var sizeTests = []struct { @@ -395,3 +396,55 @@ func TestResponseWriterSniffsContentType(t *testing.T) { }) } } + +type signallingNopCloser struct { + io.Reader + closed chan bool +} + +func (*signallingNopCloser) Write(buf []byte) (int, error) { + return len(buf), nil +} + +func (rc *signallingNopCloser) Close() error { + close(rc.closed) + return nil +} + +// Test whether server properly closes connection when processing slow +// requests +func TestSlowRequest(t *testing.T) { + pr, pw := io.Pipe() + go func(w io.Writer) { + for _, buf := range [][]byte{ + streamBeginTypeStdin, + makeRecord(typeStdin, 1, nil), + } { + pw.Write(buf) + time.Sleep(100 * time.Millisecond) + } + }(pw) + + rc := &signallingNopCloser{pr, make(chan bool)} + handlerDone := make(chan bool) + + c := newChild(rc, http.HandlerFunc(func( + w http.ResponseWriter, + r *http.Request, + ) { + w.WriteHeader(200) + close(handlerDone) + })) + go c.serve() + defer c.cleanUp() + + timeout := time.After(2 * time.Second) + + <-handlerDone + select { + case <-rc.closed: + t.Log("FastCGI child closed connection") + case <-timeout: + t.Error("FastCGI child did not close socket after handling request") + } +}