Skip to content

Commit

Permalink
http2: set up the timer of closing idle connection after the initiali…
Browse files Browse the repository at this point in the history
…zation

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]>
  • Loading branch information
panjf2000 authored and gopherbot committed May 16, 2024
1 parent 8aa6dbf commit c87a5b6
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
10 changes: 6 additions & 4 deletions http2/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,10 +826,6 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHoo
hooks.newclientconn(cc)
c = cc.tconn
}
if d := t.idleConnTimeout(); d != 0 {
cc.idleTimeout = d
cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout)
}
if VerboseLogs {
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
}
Expand Down Expand Up @@ -893,6 +889,12 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHoo
return nil, cc.werr
}

// Start the idle timer after the connection is fully initialized.
if d := t.idleConnTimeout(); d != 0 {
cc.idleTimeout = d
cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout)
}

cc.goRun(cc.readLoop)
return cc, nil
}
Expand Down
25 changes: 25 additions & 0 deletions http2/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5426,3 +5426,28 @@ func TestTransportDataAfter1xxHeader(t *testing.T) {
}
tc.wantFrameType(FrameRSTStream)
}

func TestIssue66763Race(t *testing.T) {
tr := &Transport{
IdleConnTimeout: 1 * time.Nanosecond,
AllowHTTP: true, // issue 66763 only occurs when AllowHTTP is true
}
defer tr.CloseIdleConnections()

cli, srv := net.Pipe()
donec := make(chan struct{})
go func() {
// Creating the client conn may succeed or fail,
// depending on when the idle timeout happens.
// Either way, the idle timeout will close the net.Conn.
tr.NewClientConn(cli)
close(donec)
}()

// The client sends its preface and SETTINGS frame,
// and then closes its conn after the idle timeout.
io.ReadAll(srv)
srv.Close()

<-donec
}

0 comments on commit c87a5b6

Please sign in to comment.