http2: avoid race in server handler SetReadDeadine/SetWriteDeadline

Can't safely access responseWriter.rws from on the server's serve loop.

Change-Id: I477abe58cf9dd23813a0c5507aed2319696fdfaf
Reviewed-on: https://go-review.googlesource.com/c/net/+/589856
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/http2/server.go b/http2/server.go
index d23640d..6c349f3 100644
--- a/http2/server.go
+++ b/http2/server.go
@@ -2821,9 +2821,9 @@
 		if deadline.IsZero() {
 			st.readDeadline = nil
 		} else if st.readDeadline == nil {
-			st.readDeadline = sc.srv.afterFunc(deadline.Sub(w.rws.conn.srv.now()), st.onReadTimeout)
+			st.readDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onReadTimeout)
 		} else {
-			st.readDeadline.Reset(deadline.Sub(w.rws.conn.srv.now()))
+			st.readDeadline.Reset(deadline.Sub(sc.srv.now()))
 		}
 	})
 	return nil
@@ -2847,9 +2847,9 @@
 		if deadline.IsZero() {
 			st.writeDeadline = nil
 		} else if st.writeDeadline == nil {
-			st.writeDeadline = sc.srv.afterFunc(deadline.Sub(w.rws.conn.srv.now()), st.onWriteTimeout)
+			st.writeDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onWriteTimeout)
 		} else {
-			st.writeDeadline.Reset(deadline.Sub(w.rws.conn.srv.now()))
+			st.writeDeadline.Reset(deadline.Sub(sc.srv.now()))
 		}
 	})
 	return nil
diff --git a/http2/server_test.go b/http2/server_test.go
index f877015..47c3c61 100644
--- a/http2/server_test.go
+++ b/http2/server_test.go
@@ -4661,3 +4661,16 @@
 	})
 	<-donec
 }
+
+func TestServerSetReadWriteDeadlineRace(t *testing.T) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
+		ctl := http.NewResponseController(w)
+		ctl.SetReadDeadline(time.Now().Add(3600 * time.Second))
+		ctl.SetWriteDeadline(time.Now().Add(3600 * time.Second))
+	})
+	resp, err := ts.Client().Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	resp.Body.Close()
+}