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

Work on CAMEL-26634 started by shashank.
----------------------------------------
> camel-core - Resequence EIP: batch mode can run two senders after a route 
> restart
> ---------------------------------------------------------------------------------
>
>                 Key: CAMEL-26634
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26634
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> Found with Fray (controlled concurrency testing for the JVM): a test that 
> sends to a batch resequencer while its route is stopped and started logged 
> {{java.util.ConcurrentModificationException}} at 
> {{Resequencer$BatchSender.sendExchanges}} (the {{TreeSet}} iterator) in 2 of 
> 60 schedules.
> Since CAMEL-20435 every start creates a new {{BatchSender}} thread, and 
> {{doStop}} only interrupts the old one ({{cancel()}} = {{interrupt()}}). The 
> stop does not wait for the exchange the old sender is delivering (the 
> resequencer completes the incoming exchanges when it queues them, so the 
> route has nothing inflight). If the route is started again before the old 
> sender finishes that exchange, the old sender goes on: {{while 
> (isRunAllowed())}} is true again, so it continues with its batch and its next 
> rounds (it only ends at the interruptible {{await}}, and only while its 
> interrupt status is still set). Both senders then iterate and remove from the 
> same {{collection}} (a {{TreeSet}}, shared by all senders):
> - the new sender delivers the rest of the old batch while the old sender is 
> still delivering an earlier exchange, so the exchanges are no longer 
> delivered one at a time in order (a test sees 2, 3, 4 delivered before 1 is 
> done);
> - the old sender's iterator then fails with 
> {{ConcurrentModificationException}};
> - when the downstream processing clears the interrupt status (some libraries 
> swallow it), the old sender never ends: two senders run on the same 
> collection until the route is stopped again, and every such restart can add 
> one more.
> Reproducer (plain JUnit, latches, no sleep): 
> {{batch().size(2).timeout(60000)}}; the processor of message 1 waits; 
> meanwhile 2 waits in the collection; stop and start the route; send 3 and 4. 
> On main the mock gets 2, 3, 4 before 1; with a processor that clears the 
> interrupt status, two "Batch Sender" threads stay alive.
> Ways to get there: any stop + start of the route (JMX, dev console, control 
> bus, CLI, route policies) while the resequencer delivers a slow exchange.
> Expected: one sender at a time, so the exchanges are sent in order also 
> across a restart, and the old sender ends.
> Suggested fix: a {{cancelled}} flag next to the interrupt (checked by the 
> sender loop), and the sender of a new start waits for the previous sender to 
> end before it sends anything (the start itself does not wait).
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to