http2: fix channel double-close crash

When an active http2 connection closed, a stream's done channel could
be closed twice and panic.

Fixes golang/go#13924

Change-Id: I5e050b2788070321131ca2756a899f968e9bc0b2
Reviewed-on: https://go-review.googlesource.com/18571
Reviewed-by: Andrew Gerrand <adg@golang.org>
diff --git a/http2/transport_test.go b/http2/transport_test.go
index 7183ccb..4a42f66 100644
--- a/http2/transport_test.go
+++ b/http2/transport_test.go
@@ -1263,3 +1263,42 @@
 		t.Errorf("Read = %v, %#v; want error %#v", n, err, want)
 	}
 }
+
+// golang.org/issue/13924
+// This used to fail after many iterations, especially with -race:
+// go test -v -run=TestTransportDoubleCloseOnWriteError -count=500 -race
+func TestTransportDoubleCloseOnWriteError(t *testing.T) {
+	var (
+		mu   sync.Mutex
+		conn net.Conn // to close if set
+	)
+
+	st := newServerTester(t,
+		func(w http.ResponseWriter, r *http.Request) {
+			mu.Lock()
+			defer mu.Unlock()
+			if conn != nil {
+				conn.Close()
+			}
+		},
+		optOnlyServer,
+	)
+	defer st.Close()
+
+	tr := &Transport{
+		TLSClientConfig: tlsConfigInsecure,
+		DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+			tc, err := tls.Dial(network, addr, cfg)
+			if err != nil {
+				return nil, err
+			}
+			mu.Lock()
+			defer mu.Unlock()
+			conn = tc
+			return tc, nil
+		},
+	}
+	defer tr.CloseIdleConnections()
+	c := &http.Client{Transport: tr}
+	c.Get(st.ts.URL)
+}