QGrpcHttp2Channel: finish and cancel active streams on destruction
Destroying a channel with active streams never cancelled them on the
wire. The QHttp2Connection is parented to the transport socket, so the
implicitly defaulted destructor of QGrpcHttp2ChannelPrivate destroyed
it from inside the socket's QObject destructor. At that point the
socket's derived type is already gone and QHttp2Stream::~QHttp2Stream
skips its RST_STREAM frame (getSocket() resolves to nullptr), so the
peer cannot distinguish a deliberate cancellation from a connection
loss.
Delete the connection explicitly while the socket is still intact, and
flush the socket afterwards, since the socket destructor discards any
unsent data. Disconnect the socket's signals first so no error handler
runs on a channel that is mid-destruction. Also reset m_connection
before deleting it in handleSocketError() so a reentrant socket error
cannot double-delete it.
The client side was equally silent: pending operations never received
finished() and appeared to hang forever. Emit finish with Unavailable
for every active handler before tearing down the transport, so callers
observe the channel's destruction.
The regression test drives a minimal HTTP/2 server that acknowledges
the client preface, waits for the request HEADERS, and asserts that an
RST_STREAM frame arrives when the channel is destroyed with the call
still in flight, and that the call locally finishes with Unavailable.
Pick-to: 6.12 6.11 6.8
Change-Id: Ia1e87d57857d48cd15b87e2c3b71e50b419d6d45
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>