[ 
https://issues.apache.org/jira/browse/CAMEL-24800?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-24800 started by Federico Mariani.
------------------------------------------------
> 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
>            Assignee: Federico Mariani
>            Priority: Major
>         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)

Reply via email to