shashank created CAMEL-26601:
--------------------------------

             Summary: camel-core - Recipient list in a doTry: a producer that 
throws from process(exchange, callback), such as seda with a full queue, hangs 
the exchange
                 Key: CAMEL-26601
                 URL: https://issues.apache.org/jira/browse/CAMEL-26601
             Project: Camel
          Issue Type: Bug
          Components: camel-core
            Reporter: shashank
            Assignee: shashank


Follow-up of CAMEL-26464 (and CAMEL-26445, CAMEL-26446, CAMEL-26461): the same 
hang for the one case none of them covers, a recipient of a recipient list 
inside a {{doTry}}.

Found with a SPIN model of the multicast sub task, confirmed with tests on the 
real classes.

Inside a {{doTry}}, {{MulticastProcessor.wrapInErrorHandler}} does not wrap a 
recipient in an error handler: the recipient gets only the unit of work 
processor. For a multicast the output is a channel, which catches a throw since 
CAMEL-26464; for a recipient list the output is the producer of the recipient 
endpoint. When that producer throws from {{process(exchange, callback)}} 
instead of setting the exception on the exchange, the exception reaches the sub 
task, the reactive executor drops it, and the recipient list never completes. 
The caller waits for good (a {{ProducerTemplate.send}} never returns, a 
consumer thread stays blocked). This happens with the default options and with 
{{synchronous}}, {{parallelProcessing}}, {{stopOnException}} and 
{{shareUnitOfWork}}. With a {{timeout}} the recipient list returns after the 
timeout without the failure, so the {{doCatch}} does not run either. Outside a 
{{doTry}} the error handler around the recipient handles it.

A producer in Camel itself does this: the seda producer throws 
{{IllegalStateException: Queue full}} from {{process(exchange, callback)}} when 
its bounded queue is full and neither {{blockWhenFull}} nor {{discardWhenFull}} 
is set (the default, documented as "an exception will be thrown stating that 
the queue is full"). Other component producers that throw from 
{{process(exchange, callback)}} hang the same way.

{code:java}
from("direct:start")
    .doTry()
        .recipientList(constant("seda:work?size=1"))
        .end()
        .to("mock:result")
    .endDoTry()
    .doCatch(IllegalStateException.class)
        .to("mock:caught")
    .end();

template.sendBody("seda:work?size=1", "first");   // fills the queue (no 
consumer yet)
template.sendBody("direct:start", "second");      // never returns; expected: 
mock:caught gets it
{code}

*Proposal* (main only, it builds on CAMEL-26464)
* When the multicast does not wrap the output in an error handler, let its unit 
of work processor catch the throw with the rule of CAMEL-26464 
({{CamelInternalProcessor}} catchProcessorThrows): the copy is failed with the 
exception, its unit of work is done (a copy with its own unit of work leaves 
the inflight registry, and its completed or failed event fires), and the 
multicast is continued exactly once, so the {{doCatch}} gets it. A catch in the 
sub task itself would fix the hang but skip the unit of work of the copy.
* camel-seda should also set the exception instead of throwing when the queue 
is full (a separate issue); this change is still needed for other producers 
that throw.

_Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to