shashank created CAMEL-25002:
--------------------------------
Summary: Loop EIP: a negative or very large loop count makes
graceful shutdown stop without waiting for inflight exchanges
Key: CAMEL-25002
URL: https://issues.apache.org/jira/browse/CAMEL-25002
Project: Camel
Issue Type: Bug
Components: camel-core
Reporter: shashank
{{LoopProcessor}} adds the evaluated loop count to its pending task counter
without checking the sign ({{taskCount.add(count)}}). A count of zero or less
runs no iteration, and nothing removes a negative add again. After a single
message with, for example, {{loop(header("n"))}} and {{n=-1}},
{{getPendingExchangesSize()}} returns -1 for the rest of the route's life.
{{DefaultShutdownStrategy}} adds the pending sizes of the route's services to
the inflight count (in {{int}}) and waits only while the sum is positive. The
same {{LoopProcessor}} is a child of several route services and is counted once
for each of them. The negative value therefore cancels real inflight exchanges:
a graceful stop returns immediately, and the inflight exchange fails with a
{{RejectedExecutionException}}. A very large loop count (from about 2^29) has
the same effect, because the {{int}} sum overflows.
With {{breakOnShutdown}}, a loop that breaks out leaves its remaining
iterations pending, so every later shutdown waits for its full timeout
({{LoopBreakOnShutdownTest}} takes about 10 s because of this).
Observed: after one message with {{n=-1}}, stopping the route takes 0 ms
instead of waiting for the inflight exchange, which then fails with
{{RejectedExecutionException}}. With {{n=0}} or {{n=2}}, the stop waits and the
exchange completes.
History: CAMEL-15578 clamped the gap with {{Math.max(count - index, 0)}}.
CAMEL-16794 switched to a {{LongAdder}} with an unconditional {{add(count)}}
and dropped the clamp. CAMEL-19738 added the per-iteration decrement for the
early-exit case only. CAMEL-18713 fixed a similar symptom for {{loopDoWhile}}.
Proposed fix: only add a positive count, release the iterations left exactly
once whenever the loop ends (normally, on an exception, or when it breaks on
shutdown), and in {{DefaultShutdownStrategy}} sum the pending sizes as a
{{long}}, ignore negative sizes and cap the result. A PR with regression tests
follows.
Found with a Lean 4 model of the pending-count arithmetic, then reproduced
against the real classes.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)