Skip to content

Commit c87a5b6

Browse files
panjf2000gopherbot
authored andcommitted
http2: set up the timer of closing idle connection after the initialization
Fixes golang/go#66763 Change-Id: I046028b6072a6da77e7f1b4d1f2e6b14f8edb042 Reviewed-on: https://go-review.googlesource.com/c/net/+/578115 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Damien Neil <[email protected]> Auto-Submit: Damien Neil <[email protected]>
1 parent 8aa6dbf commit c87a5b6

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

Diff for: http2/transport.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -826,10 +826,6 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHoo
826826
hooks.newclientconn(cc)
827827
c = cc.tconn
828828
}
829-
if d := t.idleConnTimeout(); d != 0 {
830-
cc.idleTimeout = d
831-
cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout)
832-
}
833829
if VerboseLogs {
834830
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
835831
}
@@ -893,6 +889,12 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHoo
893889
return nil, cc.werr
894890
}
895891

892+
// Start the idle timer after the connection is fully initialized.
893+
if d := t.idleConnTimeout(); d != 0 {
894+
cc.idleTimeout = d
895+
cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout)
896+
}
897+
896898
cc.goRun(cc.readLoop)
897899
return cc, nil
898900
}

Diff for: http2/transport_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -5426,3 +5426,28 @@ func TestTransportDataAfter1xxHeader(t *testing.T) {
54265426
}
54275427
tc.wantFrameType(FrameRSTStream)
54285428
}
5429+
5430+
func TestIssue66763Race(t *testing.T) {
5431+
tr := &Transport{
5432+
IdleConnTimeout: 1 * time.Nanosecond,
5433+
AllowHTTP: true, // issue 66763 only occurs when AllowHTTP is true
5434+
}
5435+
defer tr.CloseIdleConnections()
5436+
5437+
cli, srv := net.Pipe()
5438+
donec := make(chan struct{})
5439+
go func() {
5440+
// Creating the client conn may succeed or fail,
5441+
// depending on when the idle timeout happens.
5442+
// Either way, the idle timeout will close the net.Conn.
5443+
tr.NewClientConn(cli)
5444+
close(donec)
5445+
}()
5446+
5447+
// The client sends its preface and SETTINGS frame,
5448+
// and then closes its conn after the idle timeout.
5449+
io.ReadAll(srv)
5450+
srv.Close()
5451+
5452+
<-donec
5453+
}

0 commit comments

Comments
 (0)