You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are two http2.Transport parameters that control detection of stalled connections: ReadIdleTimeout and PingTimeout. If no data is read from a connection after ReadIdleTimeout, a PING frame is sent. If no response is received to the ping within PingTimeout, the connection is closed.
However, the ping timeout starts after the ping is sent. If a connection is write-blocked so that the PING frame cannot be written, the PingTimeout timer never starts and the connection is never closed.
Sample test case:
funcTestTransportPingWriteBlocks(t*testing.T) {
st:=newServerTester(t,
func(w http.ResponseWriter, r*http.Request) {},
optOnlyServer,
)
deferst.Close()
tr:=&Transport{
TLSClientConfig: tlsConfigInsecure,
DialTLS: func(network, addrstring, cfg*tls.Config) (net.Conn, error) {
s, c:=net.Pipe()
gofunc() {
// Read initial handshake frames.// Without this, we block indefinitely in newClientConn,// and never get to the point of sending a PING.varbuf [1024]bytes.Read(buf[:])
}()
returnc, nil
},
PingTimeout: 1*time.Second,
ReadIdleTimeout: 1*time.Second,
}
defertr.CloseIdleConnections()
c:=&http.Client{Transport: tr}
_, err:=c.Get(st.ts.URL)
iferr==nil {
t.Fatalf("Get = nil, want err")
}
}
(Another issue I just noticed while writing this test case is that if a connection becomes write-blocked while sending the initial handshake frames, we never even reach the point of sending a PING. This is unlikely in practice, because the initial handshake will almost certainly fit in the socket's send buffer, but still.)
The PingTimeout timer should probably start when we start trying to write the PING frame.
In addition, I think we might want an additional knob on http2.Transport to catch write-blocked connections in general:
// WriteTimeout is the timeout after which the connection will be closed
// if no data can be written to it. The timeout begins when data is written
// to the connection, and is extended if any bytes can be written.
// If zero, no write timeout is set.
WriteTimeout time.Duration
In particular, a write timeout would detect stalled connections in cases where the user doesn't want to constantly ping the connection for responsiveness.
The text was updated successfully, but these errors were encountered:
We start the PingTimeout timer before writing a PING frame.
However, writing the frame can block indefinitely (either
acquiring cc.wmu or writing to the conn), and the timer is
not checked until after the frame is written.
Move PING writes into a separate goroutine, so we can detect
write-blocked connections.
Fixesgolang/go#48810.
Change-Id: Ifd67fa23799e750d02754e1fe5d32719f60faed4
Reviewed-on: https://go-review.googlesource.com/c/net/+/354389
Trust: Damien Neil <[email protected]>
Run-TryBot: Damien Neil <[email protected]>
Reviewed-by: Brad Fitzpatrick <[email protected]>
There are two
http2.Transport
parameters that control detection of stalled connections:ReadIdleTimeout
andPingTimeout
. If no data is read from a connection afterReadIdleTimeout
, a PING frame is sent. If no response is received to the ping withinPingTimeout
, the connection is closed.However, the ping timeout starts after the ping is sent. If a connection is write-blocked so that the PING frame cannot be written, the
PingTimeout
timer never starts and the connection is never closed.Sample test case:
(Another issue I just noticed while writing this test case is that if a connection becomes write-blocked while sending the initial handshake frames, we never even reach the point of sending a PING. This is unlikely in practice, because the initial handshake will almost certainly fit in the socket's send buffer, but still.)
The
PingTimeout
timer should probably start when we start trying to write the PING frame.In addition, I think we might want an additional knob on
http2.Transport
to catch write-blocked connections in general:In particular, a write timeout would detect stalled connections in cases where the user doesn't want to constantly ping the connection for responsiveness.
The text was updated successfully, but these errors were encountered: