[qt/qt/qtgrpc]: Summary of bulk changes made
KDE Git Services - Bulk Change <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git repository change summary for qt/qt/qtgrpc Pushed by mirror-service into branch '6.12'. Changed from a69c46871cdae514148a7cea9f5b3fefea264817 to 15cfbac8e8944025f409202dc3f48d25122eddf1 Acknowledgement was received that this change introduces only existing code that has been pushed to another public open source repository. This change contains the following new commits: Git commit 4c7b62400399d51c579e3dd7f299ff9b73161809 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. test(end2end/interceptors): fail by throwing instead of aborting The test redefined QTEST_FAIL_ACTION to call std::abort() so that the QTest macros could be used inside non-void helpers and callbacks. Any failing check therefore killed the binary: SIGABRT locally, exit code 0xC0000409 on Windows. The XML log was truncated mid-run, so qt-testrunner reported "the test executable probably crashed" instead of the actual failure and could not re-run the failed function. Define QTEST_THROW_ON_FAIL/QTEST_THROW_ON_SKIP instead. The macros then expand to a throw expression, which compiles in non-void contexts; the testlib harness catches the exception, records the failure, and the remaining tests keep running and produce a parseable XML log. Checks running on the mock server's completion-queue thread keep their fatal behavior, as the exception terminates the process there, like abort() did. Pick-to: 6.11 Change-Id: Id565991f6c545016d606e762430ade55b252d5ee Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit 99c2d5308c476dde5848d02b4aa21f610338bf68) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/4c7b62400399d51c579e3dd7f299ff9b73161809 Git commit 2c8eaf657e54c9e7b8f2e00c3dc530335e1ee607 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. QGrpcHttp2Channel: drain the outgoing queue iteratively Http2Handler::processQueue() dequeued a single message and sent it, relying on the uploadFinished handler to call processQueue() again for the next one. On a fast link sendDATA() completes synchronously and emits uploadFinished from within the call, so a large backlog drained through one deep recursion (processQueue -> sendDATA -> uploadFinished -> processQueue -> ...), one stack frame per queued message. Burst-writing more than ~10k small messages overflowed the stack and crashed the client with SIGSEGV. Flatten the drain into a loop guarded against re-entrancy: a re-entrant processQueue() call flags and returns, while the active loop dequeues the next message. This resolves the recursion. [ChangeLog][QtGrpc][QGrpcHttp2Channel] Fixed a stack overflow that could crash the client when burst-writing a very large number of messages on a client-streaming or bidirectional RPC. Fixes: QTBUG-148062 Task-number: QTBUG-147934 Pick-to: 6.11 6.8 Change-Id: I058a9e3428ea94aad663fdf392949624702f750a Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit 378ea257f8ced5e52430d6e587025205f20e4240) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/2c8eaf657e54c9e7b8f2e00c3dc530335e1ee607 Git commit 8a839ed33b7fbf23c715538ab7f2c2dc14aa1b94 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. QGrpcHttp2Channel: validate server-sent grpc-status range The parsed value was cast directly to StatusCode without a range check. A hostile server could send e.g. "99" or "-1", narrowing into an undefined StatusCode enumerator that application switch statements may branch on unpredictably. Reject any value outside [0, Unauthenticated] with StatusCode::Unknown instead, mirroring upstream gRPC's own GRPC_STATUS_UNKNOWN fallback for invalid status codes. Pick-to: 6.11 6.8 Fixes: QTBUG-148148 Change-Id: Ib251e39459cd44786e9264e2b4e6657ae8b6128e Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit 73e54ca3dc29465412d23ec80d5473d7010c4276) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/8a839ed33b7fbf23c715538ab7f2c2dc14aa1b94 Git commit 5a997d6a9d4458b414275a1332b3b6ec3b48efe9 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. QGrpcHttp2Channel: sanitize server-controlled bytes in warning logs Three qCWarning calls printed server-controlled header keys and values via printf-style %s, letting a hostile server inject newlines, NUL bytes, or other control characters into the log stream (CWE-117). Wrap each server-supplied operand in sanitizedForLog(), which delegates to QtDebugUtils::toPrintable() to escape non-printable bytes and bound the logged output at 256 bytes, preventing log flooding. As a drive-by, fix the "unexcpected" typo in the grpc-reserved-header messages. Pick-to: 6.11 6.8 Fixes: QTBUG-148149 Change-Id: Icbd4a73a3ffb0890a4b9abe4144ecca47d87c873 Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit ae0cd2f5e8d06e56940c94fcce4c0ca83cfbcbd6) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/5a997d6a9d4458b414275a1332b3b6ec3b48efe9 Git commit e945427216a95986b123bc7a94a7e54d5564af48 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. 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.11 6.8 Change-Id: Ia1e87d57857d48cd15b87e2c3b71e50b419d6d45 Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit 497afb0eaeae3445f542f7aed4fc5d792c602bb4) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/e945427216a95986b123bc7a94a7e54d5564af48 Git commit c5b260ce589fa3bc220cb6af80f525e0ef9a24a5 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. test(end2end): move QTest::failOnWarning into init() It had no real effect in initTestCase. Change-Id: I52d5ed0cc06ecda75413b8cf24b37e8b0d079c36 Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit 9a33b4eb625ffb42d57c6d3046da12a570ede6d7) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/c5b260ce589fa3bc220cb6af80f525e0ef9a24a5 Git commit 3412e50492bed19339e3f6f45e553c529004aa1b by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. QGrpcHttp2Channel: fix maximumReceiveMessageSize(0) semantics Amends 8c8f0e3cffa4003cd549a0a6761297f53e1a5f75. A limit of 0 was silently expanded to the transport cap, making it effectively unlimited. The value is now used verbatim: 0 accepts only zero-length messages, giving callers a consistent "value is the limit" contract and removing a hidden special case. Also unify the environment variable handling for other env-vars that will be introduced after this commit, and picked back manually into older branches. This commit is the first of its kind, so we do it here already: * Introduced 'macro.h2EnvFallback' to unify the environment fallbacks * readEnvUnsignedInt(const char *name) * doc section: 'Environment variable fallbacks' Found before the QtGRPC API review. Task-number: QTBUG-145258 Task-number: QTBUG-145399 Fixes: QTBUG-146592 Change-Id: I0fc2780b6d6ddbffed2466cfe8d92d1c0324b2c5 Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit c3f2aaa4854a1b5ff11c064c79f3f0bc0efac8ba) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/3412e50492bed19339e3f6f45e553c529004aa1b Git commit 52b92943732fcfe78335444da3002ba23b8f90e3 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:15.. mockserver: stack-allocate TagProcessor in tests Tests created their TagProcessor via MockServer::createProcessor(), which returned a unique_ptr. Lambdas captured that unique_ptr by reference and called processor.get() when they fired later. libc++'s std::unique_ptr::reset() nulls the stored pointer before it invokes the deleter. So while ~TagProcessor() blocked in waitForTagCompletion(5s), the TagProcessor object itself was alive (that is the whole reason it waits, since Finish completions are expected to arrive after the client has already finished) yet processor.get() read through the unique_ptr already returned nullptr. Any callback that constructed a new tag in that window forwarded the null into AbstractTag and crashed on processor->registerTag(this). The previous workaround captured processor.get() up front at a single call site. Every test in this file (and in the interceptors test) followed the same [&] / processor.get() pattern, so the possibility for a crash existed at every call site. This flaky behavior got observed in recent CI runs. Drop MockServer::createProcessor() and stack-allocate TagProcessor: TagProcessor processor(m_server.get()); The address of a stack object is stable for its entire lifetime, including while its destructor runs, so &processor in a callback is always a valid TagProcessor*. There is no smart-pointer indirection left to lie about the pointee. Change-Id: Iebec19bce57879778b2b5a5c0e94ce00ca62945d Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit 7fe45ea97d20932057ecee7b0d2337934d38f136) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/52b92943732fcfe78335444da3002ba23b8f90e3 Git commit 15cfbac8e8944025f409202dc3f48d25122eddf1 by Qt Cherry-pick Bot (on behalf of Dennis Oberst) on 21/07/2026 at 20:16.. QGrpcHttp2Channel: raise the default HTTP/2 receive window A bare QHttp2Configuration advertises only a 64 KiB receive window for both the stream and the connection. HTTP/2 flow control bounds the unacknowledged data the peer may send, so download throughput is capped at window/RTT: on a fast link the sender stalls waiting for WINDOW_UPDATE frames and the pipe sits idle. Default to a 4 MiB per-stream and 16 MiB per-connection receive window. The connection window is kept the larger of the two so it never bottlenecks multiplexed streams; both match the windows used by the C++ gRPC reference and Go's net/http2. Measured with tests/manual/grpc/benchmarks (asyncbenchserver, 1000 calls, http loopback, arm64 macOS), stock vs. patched: payload RPC before after delta 16 KiB ServerStreaming 428 MB/s 1.10 GB/s +157% 256 KiB ServerStreaming 470 MB/s 2.68 GB/s +471% 1 MiB ServerStreaming 471 MB/s 2.98 GB/s +533% (2.23 s → 353 ms) 1 MiB BidiStreaming 743 MB/s 2.31 GB/s +211% (2.82 s → 910 ms) 1 MiB UnaryCall 747 MB/s 1.89 GB/s +153% (2.81 s → 1.11 s) UnaryCall server→client response latency at 1 MiB drops from 2.19 ms to 454 µs (−79%). Small messages stay within run-to-run noise, and upload-only ClientStreaming is unchanged because the client receive window does not govern outbound data. [ChangeLog][QtGrpc][QGrpcHttp2Channel] The default HTTP/2 receive window was raised from 64 KiB to 4 MiB per stream and 16 MiB per connection. The per-stream window can be tuned via the QT_GRPC_HTTP2_STREAM_RECEIVE_WINDOW_SIZE environment variable and the connection window via QT_GRPC_HTTP2_CONNECTION_RECEIVE_WINDOW_SIZE Pick-to: 6.11 6.8 Fixes: QTBUG-136766 Change-Id: Ide6ae9dd941283519052632db7165583d1002a00 Reviewed-by: Ivan Solovev <[email protected]> (cherry picked from commit 0427da31b4fccfc6889cd96f3beda98fdf1a2cce) Reviewed-by: Qt Cherry-pick Bot <[email protected]> https://invent.kde.org/qt/qt/qtgrpc/-/commit/15cfbac8e8944025f409202dc3f48d25122eddf1