shashank created CAMEL-26605:
--------------------------------

             Summary: camel-seda - receive() without a timeout never returns 
after the CamelContext, the route of a pollEnrich or the consumer template stops
                 Key: CAMEL-26605
                 URL: https://issues.apache.org/jira/browse/CAMEL-26605
             Project: Camel
          Issue Type: Bug
          Components: camel-seda
            Reporter: shashank
            Assignee: shashank


Found while testing stop and receive orderings of the polling consumers, then 
reproduced with plain JUnit tests on the real classes.

{{SedaPollingConsumer.receive()}} is {{getEndpoint().getQueue().take()}}. It 
does not look at the state of the polling consumer, so a thread that waits in 
it for a message waits for ever once nothing will put one there:

* {{consumerTemplate.receive("seda:foo")}} / {{receiveBody("seda:foo")}} (no 
timeout) in a worker thread, then the CamelContext stops: the thread never 
returns. {{SedaComponent.doStop}} clears its queues, so after a restart of the 
CamelContext new messages go to a new queue and the thread waits on the old one 
for good (with a non-daemon thread the JVM does not exit).
* {{consumerTemplate.stop()}} while a {{receive()}} waits: the same.
* {{pollEnrich("seda:foo")}} with the default timeout (-1, which calls 
{{receive()}}): stopping the route or the CamelContext waits for the in-flight 
exchange until the shutdown timeout, the forced stop then stops the polling 
consumer, but the exchange thread stays in {{take()}} for ever.

{{EventDrivenPollingConsumer}} (used by most other endpoints) checks 
{{isRunAllowed()}} every second while it waits, so it returns {{null}} in these 
cases (CAMEL-25036 made sure it can be stopped while it waits). CAMEL-25036 
noted that seda has its own polling consumer and was not affected by that lock; 
this is the seda side of the same scenario.

{code:java}
// a worker thread
Exchange exchange = consumerTemplate.receive("seda:idle");   // never returns 
after context.stop()

// a route
from("direct:start").pollEnrich("seda:idle").to("mock:result");   // the 
exchange thread never returns after stopRoute
{code}

Reproduction: a test that waits until the thread is inside 
{{SedaPollingConsumer.receive}}, then stops the CamelContext / the consumer 
template / the route (shutdown timeout 1 s), and waits 10 s for the call to 
return: all three time out on main. A control with a polling consumer that was 
never started still receives the next message.

Expected: {{receive()}} returns {{null}} once the polling consumer is stopped, 
like {{EventDrivenPollingConsumer}}; a message already in the queue is still 
returned; a polling consumer that was never started keeps waiting (the current 
behaviour, which code that calls {{endpoint.createPollingConsumer().receive()}} 
without starting it may rely on).

Suggested fix: wait with {{poll(1 s)}} in a loop and return {{null}} when the 
polling consumer is stopping, stopped or shut down (not when it was never 
started).

_Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to