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)