From a51b03bc32e2c8ec5e02a3690f0244453ddfb283 Mon Sep 17 00:00:00 2001 From: jacktengg Date: Wed, 27 May 2026 16:13:57 +0800 Subject: [PATCH] [fix](be) Fix DCHECK in LocalExchangeSharedState::sub_total_mem_usage Issue Number: close #xxx Problem Summary: In LocalExchangeSharedState::sub_total_mem_usage(), `mem_usage` is `std::atomic` but `delta` is `size_t`. The existing debug check DCHECK_GE(prev_usage - delta, 0); was never effective: the usual arithmetic conversions promote `prev_usage - delta` to `size_t`, and an unsigned expression is trivially `>= 0`. So the guard against `mem_usage` underflow (subtracting more than was added) silently passed in all debug builds, leaving any over-subtraction undetected. Fix: compare `prev_usage` (int64_t) against `cast_set(delta)` so the comparison is performed entirely in signed space, and a real underflow will actually trip the DCHECK with the original prev_usage and delta values in the failure message. The release-mode guard on the next line (`cast_set(prev_usage - delta)` throws on underflow because the wrapped size_t result exceeds INT64_MAX) is preserved as-is. --- be/src/exec/pipeline/dependency.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/be/src/exec/pipeline/dependency.h b/be/src/exec/pipeline/dependency.h index 9ffbb2c5c7ab5e..b08dd1867108a8 100644 --- a/be/src/exec/pipeline/dependency.h +++ b/be/src/exec/pipeline/dependency.h @@ -927,7 +927,8 @@ struct LocalExchangeSharedState : public BasicSharedState { void sub_total_mem_usage(size_t delta) { auto prev_usage = mem_usage.fetch_sub(delta); - DCHECK_GE(prev_usage - delta, 0) << "prev_usage: " << prev_usage << " delta: " << delta; + DCHECK_GE(prev_usage, cast_set(delta)) + << "prev_usage: " << prev_usage << " delta: " << delta; if (cast_set(prev_usage - delta) <= _buffer_mem_limit) { sink_deps.front()->set_ready(); }