Federico Mariani created CAMEL-24800:
----------------------------------------
Summary: camel-core - pooled exchange copies share the parent's
clock, so Splitter children are returned to the pool without reset
(properties/variables leak between messages)
Key: CAMEL-24800
URL: https://issues.apache.org/jira/browse/CAMEL-24800
Project: Camel
Issue Type: Bug
Components: camel-core
Affects Versions: 4.22.0
Reporter: Federico Mariani
Attachments: PooledExchangeSplitLeakTest.java
When exchange pooling is enabled ({{PooledExchangeFactory}} +
{{PooledProcessorExchangeFactory}}), the Splitter's child exchanges are
returned to the pool *without being reset*, so exchange properties and
exchange-scoped variables set while processing one message leak into the
children of the next message that goes through the same split.
*Cause*: {{DefaultPooledExchange(Exchange parent)}} reuses the parent's
{{ResetableClock}} instance when the parent already has one (since CAMEL-20225,
4.4):
{code:java}
if (parentClock instanceof ResetableClock rs) {
this.clock = rs; // shared with the parent
} else {
this.clock = new ResetableClock(parent.getClock());
}
{code}
The Splitter creates every child via {{createCorrelatedCopy}} from its (pooled)
working copy, so parent and child share one clock. On completion the working
copy is released first: its {{done()}} calls {{clock.unset()}} (created = 0).
The child's {{done()}} then hits the guard {{if (clock.getCreated() > 0)}} and
skips the whole reset (properties, variables, extension flags, message), and
the dirty exchange is offered back to the pool.
*Reproducer* (attached as a unit test): pooled factories,
{{from("direct:start").split(body()).process(...).to("mock:split")}}; the child
of the first message sets an exchange property and a variable; the child of the
second message must not see them, but sees both ({{leakProp=from-first}},
{{leak=from-first}}). Headers do not leak because reuse overwrites the message.
*Fix*: give every pooled copy its own clock ({{new
ResetableClock(parentClock)}} unconditionally). Verified: the reproducer passes
with that change. Not a regression of a specific release; present since 4.4.
_Claude Code on behalf of Federico Mariani_
--
This message was sent by Atlassian Jira
(v8.20.10#820010)