Skip to content

[fix](rpc) Fix AutoReleaseClosure data race with callback reuse#61782

Draft
zclllyybb wants to merge 1 commit intoapache:masterfrom
zclllyybb:brpc_closure
Draft

[fix](rpc) Fix AutoReleaseClosure data race with callback reuse#61782
zclllyybb wants to merge 1 commit intoapache:masterfrom
zclllyybb:brpc_closure

Conversation

@zclllyybb
Copy link
Copy Markdown
Contributor

The callback's call() method may reuse the callback object (e.g., in vdata_stream_sender.h get_send_callback()), triggering a new RPC that mutates response_ and cntl_. If AutoReleaseClosure::Run() invokes call() before checking cntl_->Failed() or response_->status(), it reads the NEW RPC's state instead of the ORIGINAL RPC's result, causing:

*** SIGSEGV address not mapped to object (@0x0) received by PID 238162 (TID 240463 OR 0xfffa2c9898e0) from PID 0; stack trace: ***
 0# doris::signal::(anonymous namespace)::FailureSignalHandler(int, siginfo_t*, void*) at /home/zcp/repo_center/doris_release/doris/be/src/common/signal_handler.h:421
 1# os::Linux::chained_handler(int, siginfo_t*, void*) in /opt/module/doris/java8/jre/lib/aarch64/server/libjvm.so
 2# JVM_handle_linux_signal in /opt/module/doris/java8/jre/lib/aarch64/server/libjvm.so
 3# signalHandler(int, siginfo_t*, void*) in /opt/module/doris/java8/jre/lib/aarch64/server/libjvm.so
 4# 0x0000FFFF0AB107C0 in linux-vdso.so.1
 5# doris::Status doris::Status::create<true>(doris::PStatus const&) at /home/zcp/repo_center/doris_release/doris/be/src/common/status.h:398
 6# void doris::AutoReleaseClosure<doris::PTransmitDataParams, doris::pipeline::ExchangeSendCallback<doris::PTransmitDataResult> >::_process_status<doris::PTransmitDataResult>(doris::PTransmitDataResult*) at /home/zcp/repo_center/doris_release/doris/be/src/util/ref_count_closure.h:128
 7# doris::AutoReleaseClosure<doris::PTransmitDataParams, doris::pipeline::ExchangeSendCallback<doris::PTransmitDataResult> >::Run() at /home/zcp/repo_center/doris_release/doris/be/src/util/ref_count_closure.h:102
 8# brpc::Controller::EndRPC(brpc::Controller::CompletionInfo const&) in /opt/module/doris/be/lib/doris_be
 9# brpc::policy::ProcessRpcResponse(brpc::InputMessageBase*) in /opt/module/doris/be/lib/doris_be
10# brpc::ProcessInputMessage(void*) in /opt/module/doris/be/lib/doris_be
11# bthread::TaskGroup::task_runner(long) in /opt/module/doris/be/lib/doris_be
12# bthread_make_fcontext in /opt/module/doris/be/lib/doris_be

we have confirmed the data race is real existing with temporary LOGs which has been removed:

F20260325 21:46:58.465230 3453395 brpc_closure.h:116] Check failed: _debug_generation_at_construction == current_gen (2 vs. 3) RACE DETECTED: AutoReleaseClosure response_ was reused by a new RPC (generation changed from 2 to 3) while still in Run(). The old closure is about to read response_->status() but the new RPC may be concurrently writing to the same response_ object.

and we add some be-ut which could only pass WITH this patch.
before we fix:

[----------] 7 tests from ExchangeSinkTest (5 ms total)

[----------] Global test environment tear-down
[==========] 7 tests from 1 test suite ran. (5 ms total)
[  PASSED  ] 4 tests.
[  FAILED  ] 3 tests, listed below:
[  FAILED  ] ExchangeSinkTest.test_closure_call_must_not_corrupt_status_check
[  FAILED  ] ExchangeSinkTest.test_closure_call_must_not_hide_error_status
[  FAILED  ] ExchangeSinkTest.test_closure_call_must_not_hide_rpc_failure

after:

[----------] 7 tests from ExchangeSinkTest (4 ms total)

[----------] Global test environment tear-down
[==========] 7 tests from 1 test suite ran. (5 ms total)
[  PASSED  ] 7 tests.

@zclllyybb zclllyybb added usercase Important user case type label dev/4.0.x dev/4.1.x labels Mar 26, 2026
@zclllyybb
Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen
Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@zclllyybb
Copy link
Copy Markdown
Contributor Author

run buildall

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a brpc AutoReleaseClosure race when callbacks are reused to start a new RPC (mutating response_/cntl_), by ensuring status/failure checks happen before invoking callback->call(), and adds unit tests to prevent regressions.

Changes:

  • Reorders AutoReleaseClosure::Run() so it checks cntl_ / response_->status() before invoking callback->call().
  • Refactors runtime-filter sync-size RPC handling to keep the callback alive until RPC completion.
  • Adds BE unit tests that simulate callback reuse mutating shared RPC state.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
be/test/exec/exchange/exchange_sink_test.cpp Adds tests that simulate callback reuse and verify correct ordering.
be/src/util/brpc_closure.h Reorders Run() and simplifies error handling paths.
be/src/exec/runtime_filter/runtime_filter_producer.h Adds storage to keep sync-size callback alive across async RPC.
be/src/exec/runtime_filter/runtime_filter_producer.cpp Introduces SyncSizeCallback and changes closure construction/lifetime.
be/src/exec/runtime_filter/runtime_filter_mgr.h Updates _send_rf_to_target signature (removes QueryContext arg).
be/src/exec/runtime_filter/runtime_filter_mgr.cpp Updates runtime-filter RPC closure construction (drops ctx passing).
be/src/exec/runtime_filter/runtime_filter.cpp Updates runtime-filter RPC closure construction (drops ctx passing).
be/src/exec/operator/exchange_sink_buffer.cpp Adds comments documenting callback reuse ordering constraints.
be/src/exec/exchange/vdata_stream_sender.h Documents callback reuse rationale.
Comments suppressed due to low confidence (1)

be/src/util/brpc_closure.h:1

  • This change removes the previous QueryContext-based failure propagation (and error_msg augmentation) from AutoReleaseClosure, replacing it with logging only. That’s a behavior change: some call sites previously relied on AutoReleaseClosure to cancel the query on RPC failure / non-OK status(), gated by ignore_runtime_filter_error; after this patch, errors may no longer interrupt the query and could lead to hangs or delayed failure handling. Recommendation (mandatory): restore a mechanism to propagate failures (either by reintroducing the optional QueryContext + captured status/failure info before calling tmp->call(), or by requiring callers to pass a callback that performs the cancel/sub/error handling) while keeping the call() invocation as the last step to avoid the reuse race.
// Licensed to the Apache Software Foundation (ASF) under one

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +194 to +202
auto callback = SyncSizeCallback::create_shared(_dependency, _wrapper);
// Store callback in the producer to keep it alive until the RPC completes.
// AutoReleaseClosure holds callbacks via weak_ptr, so without this the callback
// would be destroyed when this function returns and error-path sub() would never fire.
_sync_size_callback = callback;
// RuntimeFilter maybe deconstructed before the rpc finished, so that could not use
// a raw pointer in closure. Has to use the context's shared ptr.
auto closure = SyncSizeClosure::create_unique(request, callback, _dependency, _wrapper,
state->query_options().ignore_runtime_filter_error
? std::weak_ptr<QueryContext> {}
: state->get_query_ctx_weak());
auto closure = AutoReleaseClosure<PSendFilterSizeRequest, SyncSizeCallback>::create_unique(
request, callback);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_sync_size_callback is a single slot, but send_size() can be invoked more than once during the producer lifecycle in some implementations; if a second call happens before the first RPC completes, this assignment overwrites the stored callback and can still allow the earlier callback to be destroyed early (reintroducing the 'weak_ptr callback dies before completion' failure). Also, the stored callback is never cleared on completion, which can unnecessarily retain _dependency until producer teardown. Recommendation (mandatory): make the storage support multiple in-flight RPCs (e.g., vector/list keyed by RPC generation or request id), and clear the stored entry when the RPC completes (both success and error paths), e.g., by having the callback clear a weak back-reference to the producer or by clearing in the completion handler that observes the response.

Copilot uses AI. Check for mistakes.
Comment on lines 254 to +257
auto closure = AutoReleaseClosure<PSyncFilterSizeRequest,
DummyBrpcCallback<PSyncFilterSizeResponse>>::
create_unique(std::make_shared<PSyncFilterSizeRequest>(),
DummyBrpcCallback<PSyncFilterSizeResponse>::create_shared(), ctx);
DummyBrpcCallback<PSyncFilterSizeResponse>::create_shared());
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call site previously passed a QueryContext weak_ptr (conditionally based on ignore_runtime_filter_error) into AutoReleaseClosure so failures could be escalated/canceled when the option is false. With the ctx parameter removed and the callback being DummyBrpcCallback, RPC failure/non-OK status() handling appears to be reduced to logging only, which can change query correctness/termination behavior. Recommendation (mandatory): either (1) restore ctx-based cancellation semantics in AutoReleaseClosure (capturing status/failure before invoking call()), or (2) replace DummyBrpcCallback with a runtime-filter-specific callback that performs the required cancel/disable/sub behavior under the same option gating.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

PR Goal & Accomplishment

This PR fixes a real data race in AutoReleaseClosure::Run() where call() was invoked before checking cntl_->Failed() and response_->status(). Because call() can trigger callback reuse (e.g., in ExchangeSendCallback::call() -> _suc_fn -> _send_rpc() which reuses the same callback via get_send_callback()), the closure would then read mutated cntl_/response_ state from the new RPC instead of the original. The fix correctly reorders: log/check first, then call() last. The crash stacktrace and debug-log evidence clearly confirm the race.

The secondary change — removing QueryContext cancellation from AutoReleaseClosure and moving error handling into individual callbacks — is also sound. All callback types that need error handling (ExchangeSendCallback, SyncSizeCallback, WriteBlockCallback) already fully handle errors in their call() methods. The DummyBrpcCallback paths either have caller-side join()+check patterns or are fire-and-forget operations where query cancellation was too aggressive.

Compilation Bug Found

The old code had two _process_status overloads: an unconstrained no-op fallback template <typename Response> void _process_status(Response*) {} and a constrained template <HasStatus Response> void _process_status(Response*). The new code only has the constrained _log_error_status<HasStatus Response> but removed the unconstrained fallback. This will cause a compilation failure for PTabletWriterCancelResult (an empty protobuf message with no status() field), used in vtablet_writer.cpp:1229.

Critical Checkpoint Conclusions

  1. Goal accomplished? Yes, the core data race fix is correct. Tests prove the ordering. However, there is a compilation bug (see inline comment).

  2. Modification minimal and focused? Yes. The changes are well-scoped: core fix in brpc_closure.h, consequent cleanup of QueryContext removal, and SyncSizeClosure -> SyncSizeCallback refactor.

  3. Concurrency: The core fix addresses the concurrency issue correctly by ensuring call() (which may trigger callback reuse and new RPCs) is the last operation in Run(). The SyncSizeCallback::call() reads cntl_ and response_ which are safe because call() is now called before any reuse can happen.

  4. Lifecycle management: _sync_size_callback (as shared_ptr<void>) correctly keeps the SyncSizeCallback alive until the RuntimeFilterProducer is destroyed. Without this, AutoReleaseClosure's weak_ptr to the callback would expire when send_size() returns, and the error-path sub() would never fire. This is correct.

  5. Parallel code paths: The two success handler lambdas in exchange_sink_buffer.cpp (unicast and broadcast) both have the same comment added about _send_rpc being last. Good.

  6. Test coverage: Three well-designed unit tests verify the ordering invariant by capturing state at call() time and mutating afterward. Tests correctly fail with the old ordering and pass with the new.

  7. Error handling: The behavioral change from QueryContext::cancel() to LOG(WARNING) is safe — all critical paths already handle errors in their callbacks or via caller-side join()+check.

  8. No incompatible changes: No function symbol or storage format changes.

  9. Configuration: No new configs added.

  10. Observability: Error logging is preserved (downgraded from cancel to LOG(WARNING) in AutoReleaseClosure, but callbacks handle errors appropriately).

@zclllyybb
Copy link
Copy Markdown
Contributor Author

/review

@zclllyybb
Copy link
Copy Markdown
Contributor Author

run buildall

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

PR Goal

Fix a real data race in AutoReleaseClosure where call() was invoked before checking cntl_->Failed() and response_->status(). When call() reuses the callback (as in ExchangeSendCallback via get_send_callback()), it can trigger a new RPC that mutates response_ and cntl_, causing the subsequent reads to see the new RPC's state instead of the original — leading to SIGSEGV crashes.

Core Fix Assessment

The fix is correct and well-motivated:

  1. Reordering in Run(): Log/check cntl/response state before calling callback_->call(). This prevents the data race.
  2. Removing QueryContext from AutoReleaseClosure: Decentralizes error handling to individual callbacks, which is architecturally cleaner.
  3. SyncSizeCallback refactoring: Moves from subclassing AutoReleaseClosure to subclassing DummyBrpcCallback, properly handling errors in call().
  4. Unit tests: Three well-designed tests verify the ordering invariant.

Critical Checkpoint Conclusions

  • Goal accomplished? Yes, the data race is fixed by reordering call() to be last in Run(). Tests prove the ordering.
  • Modification minimal and focused? Mostly yes. The QueryContext removal is a secondary cleanup bundled with the fix.
  • Concurrency? The core race condition is correctly addressed. The callback reuse pattern in ExchangeSendCallback is safe because _send_rpc (which triggers reuse) is documented and enforced as the last operation in success handlers.
  • Lifecycle management? _sync_size_callback as shared_ptr<void> correctly keeps the callback alive. The weak_ptr in AutoReleaseClosure allows graceful degradation if the callback owner is gone.
  • Parallel code paths? Both unicast and broadcast paths in exchange_sink_buffer.cpp are updated with matching comments.
  • Error handling? See inline comment — the ignore_runtime_filter_error=false + RPC failure path that previously cancelled the query now silently degrades. The existing regression test test_inject_send_filter_size_fail.groovy expects the old cancellation behavior and will likely fail.
  • Test coverage? Good unit tests for the ordering fix. Missing update to the regression test.
  • Incompatible changes? No storage/protocol changes. The AutoReleaseClosure constructor signature change is source-breaking but all callers are updated.
  • Performance? No concerns — the reordering adds no overhead.

std::shared_ptr<RuntimeFilterWrapper> wrapper)
: _dependency(std::move(dependency)), _wrapper(wrapper) {}

void call() override {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Behavioral regression] The old SyncSizeClosure called Base::_process_if_rpc_failed() in its Defer, which would invoke ctx->cancel(Status::NetworkError("RPC meet failed: ...")) when ignore_runtime_filter_error == false. This cancelled the query on RF RPC failure.

The new SyncSizeCallback::call() gracefully degrades (disables the filter + subs dependency) but never cancels the query context, regardless of ignore_runtime_filter_error.

This breaks the existing regression test regression-test/suites/query_p0/join/test_inject_send_filter_size_fail/test_inject_send_filter_size_fail.groovy (lines 80-86), which expects:

sql "set ignore_runtime_filter_error = false"
test {
    sql "...";
    exception "RPC meet failed"
}

The test expects the query to fail with "RPC meet failed" when the debug point injects an RPC failure and ignore_runtime_filter_error=false. With this PR, the query will succeed (with degraded performance) instead.

Recommendation: Either:

  1. Update the regression test to reflect the new behavior (query succeeds even on RF RPC failure), OR
  2. Add query-context cancellation logic to SyncSizeCallback::call() when ignore_runtime_filter_error == false (requires passing the flag or a weak QueryContext to the callback).

Option 1 seems more consistent with the PR's design philosophy of graceful degradation.

create_unique(merge_filter_request, merge_filter_callback,
state->query_options().ignore_runtime_filter_error
? std::weak_ptr<QueryContext> {}
: state->get_query_ctx_weak());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Behavioral change] _push_to_remote sends a merge_filter RPC with a DummyBrpcCallback (empty call()). Previously, when ignore_runtime_filter_error == false, the old code would cancel the query context on RPC failure. Now, failures are only logged as warnings.

This is functionally safe (runtime filters are an optimization, not correctness), but the behavioral change should be documented in the PR's release notes. A merge_filter failure will result in the runtime filter never completing at the merge node — consumers will wait until the RF timeout expires, then proceed without the filter.

}
// this must be the LAST operation in this function, because call() may reuse the callback! (response_ is in callback_)
if (auto tmp = callback_.lock()) {
tmp->call();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Observation - looks good] The reordering is correct: log/check state first, then call() last. The comment clearly documents why call() must be last. This is the core fix and it correctly addresses the data race.

@doris-robot
Copy link
Copy Markdown

TPC-H: Total hot run time: 26928 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit d29c1f8898175730bb45ddfc4d4440f2f93452b2, data reload: false

------ Round 1 ----------------------------------
orders	Doris	NULL	NULL	0	0	0	NULL	0	NULL	NULL	2023-12-26 18:27:23	2023-12-26 18:42:55	NULL	utf-8	NULL	NULL	
============================================
q1	17651	4492	4276	4276
q2	q3	10669	827	540	540
q4	4699	359	252	252
q5	7581	1224	1012	1012
q6	176	174	142	142
q7	802	852	673	673
q8	10031	1490	1338	1338
q9	5473	4732	4733	4732
q10	6323	1926	1628	1628
q11	471	258	240	240
q12	755	584	467	467
q13	18029	2695	1938	1938
q14	221	236	220	220
q15	q16	729	747	672	672
q17	751	839	441	441
q18	5916	5331	5328	5328
q19	1485	974	611	611
q20	540	498	387	387
q21	4513	1849	1702	1702
q22	410	346	329	329
Total cold run time: 97225 ms
Total hot run time: 26928 ms

----- Round 2, with runtime_filter_mode=off -----
orders	Doris	NULL	NULL	150000000	42	6422171781	NULL	22778155	NULL	NULL	2023-12-26 18:27:23	2023-12-26 18:42:55	NULL	utf-8	NULL	NULL	
============================================
q1	4752	4696	4553	4553
q2	q3	3863	4338	3819	3819
q4	861	1199	768	768
q5	4065	4371	4370	4370
q6	212	184	141	141
q7	1748	1661	1570	1570
q8	2598	2722	2612	2612
q9	7582	7373	7474	7373
q10	3714	3959	3603	3603
q11	529	445	420	420
q12	536	626	469	469
q13	2557	3073	2066	2066
q14	309	312	289	289
q15	q16	744	812	880	812
q17	1212	1405	1392	1392
q18	7366	6920	6663	6663
q19	925	886	919	886
q20	2054	2129	1935	1935
q21	3927	3506	3302	3302
q22	452	426	379	379
Total cold run time: 50006 ms
Total hot run time: 47422 ms

@doris-robot
Copy link
Copy Markdown

TPC-DS: Total hot run time: 167957 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit d29c1f8898175730bb45ddfc4d4440f2f93452b2, data reload: false

query5	4337	671	519	519
query6	327	236	205	205
query7	4215	470	264	264
query8	354	241	226	226
query9	8727	2695	2699	2695
query10	505	401	339	339
query11	7041	5092	4873	4873
query12	181	131	128	128
query13	1286	479	350	350
query14	5753	3733	3430	3430
query14_1	2839	2844	2802	2802
query15	212	193	174	174
query16	1000	467	456	456
query17	886	728	629	629
query18	2448	451	348	348
query19	218	218	196	196
query20	134	125	131	125
query21	216	137	114	114
query22	13201	13431	13205	13205
query23	16166	15796	16178	15796
query23_1	16114	16303	16073	16073
query24	7820	1746	1266	1266
query24_1	1291	1281	1331	1281
query25	567	493	472	472
query26	1561	299	153	153
query27	3460	488	294	294
query28	4497	1844	1820	1820
query29	831	559	469	469
query30	298	221	188	188
query31	1008	939	871	871
query32	83	72	73	72
query33	505	329	288	288
query34	879	851	527	527
query35	662	715	599	599
query36	1042	1126	966	966
query37	140	92	86	86
query38	2910	2872	2866	2866
query39	853	826	808	808
query39_1	800	790	800	790
query40	234	157	136	136
query41	64	64	60	60
query42	258	254	255	254
query43	234	253	221	221
query44	
query45	197	185	184	184
query46	886	1037	600	600
query47	2103	2543	2047	2047
query48	315	318	229	229
query49	637	461	390	390
query50	693	270	211	211
query51	4026	4089	3986	3986
query52	263	262	255	255
query53	288	340	299	299
query54	297	267	256	256
query55	93	88	91	88
query56	315	317	320	317
query57	1876	1672	1715	1672
query58	285	281	267	267
query59	2789	2954	2716	2716
query60	339	338	318	318
query61	158	157	160	157
query62	626	583	539	539
query63	304	272	274	272
query64	5128	1350	1012	1012
query65	
query66	1468	468	358	358
query67	24236	24378	24082	24082
query68	
query69	400	310	287	287
query70	957	936	964	936
query71	324	305	299	299
query72	2876	2771	2487	2487
query73	539	542	316	316
query74	9576	9542	9401	9401
query75	2839	2764	2442	2442
query76	2299	1024	680	680
query77	387	421	313	313
query78	10825	11045	10423	10423
query79	1113	788	564	564
query80	872	637	551	551
query81	526	266	221	221
query82	1327	152	123	123
query83	331	264	245	245
query84	298	113	96	96
query85	976	508	453	453
query86	378	332	294	294
query87	3111	3101	3027	3027
query88	3547	2634	2631	2631
query89	417	372	345	345
query90	1845	177	170	170
query91	167	163	146	146
query92	80	76	72	72
query93	908	851	500	500
query94	532	339	284	284
query95	619	405	327	327
query96	652	510	227	227
query97	2491	2471	2418	2418
query98	245	220	214	214
query99	999	1001	918	918
Total cold run time: 250420 ms
Total hot run time: 167957 ms

@hello-stephen
Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 52.90% (19934/37685)
Line Coverage 36.41% (186790/512958)
Region Coverage 32.68% (144878/443363)
Branch Coverage 33.87% (63518/187534)

@hello-stephen
Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 73.60% (27165/36907)
Line Coverage 57.09% (291971/511420)
Region Coverage 54.41% (243480/447485)
Branch Coverage 56.17% (105664/188100)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev/4.0.x dev/4.1.x usercase Important user case type label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants