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

Work on CAMEL-26334 started by shashank.
----------------------------------------
> camel-once - the consumer keeps a non-daemon timer thread after its route or 
> the CamelContext stopped, and a restarted route fails to start (Task already 
> scheduled or cancelled)
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-26334
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26334
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> {{OnceConsumer}} creates a {{java.util.Timer}} in its constructor ({{new 
> Timer(endpoint.getName())}}, a non-daemon thread named after the endpoint) 
> and never cancels it: {{doStop}} only cancels the {{TimerTask}} (main 
> 8e0ce2d21371). So:
> * the thread stays alive after the route is stopped and after the 
> CamelContext is stopped; after the route is removed it ends only when the 
> consumer is garbage collected (the cleaner of {{java.util.Timer}}). Every 
> once route that was created, or reloaded in dev mode, keeps a thread until 
> then, and a non-daemon one;
> * a once route that is stopped and started again does not start: {{doStart}} 
> schedules the cancelled {{TimerTask}} again and fails with 
> {{IllegalStateException: Task already scheduled or cancelled}}. A 
> CamelContext with a once route that is stopped and started again fails to 
> start the same way, and so does the resume of a suspended once route.
> {code:java}
> from("once:tick?delay=0").routeId("r").process(e -> fired.release());
> context.start();                          // fires
> context.stop();                           // thread "tick" (non-daemon) still 
> alive 10 s later
> // 20 routes from("once:xN?delay=0") added, fired, stopped and removed: 20 
> threads alive 10 s later
> context.getRouteController().stopRoute("r");
> context.getRouteController().startRoute("r");   // IllegalStateException: 
> Task already scheduled or cancelled
> {code}
> *Fix* (proposed): the consumer fires on a single thread scheduled executor 
> that {{doStart}} creates through the {{ExecutorServiceManager}} (thread 
> {{Camel (<context>) thread #N - <name>}}). {{doStop}} cancels the pending 
> fire with {{cancel(false)}} (a fire that is routing is not interrupted, as 
> with {{TimerTask.cancel()}}) and shuts the executor down. Each start 
> schedules a new fire, so a restarted route fires again, as {{doStop}} 
> resetting {{scheduled}} intended. {{scheduleTask(TimerTask, Timer)}} becomes 
> {{scheduleTask()}}, which does nothing before the consumer started. This also 
> takes the {{TimerTask}} out of camel-once, which CAMEL-22957 listed for 
> virtual thread support. Upgrade guide entry (thread name, restart, protected 
> method).
> *Tests*: {{OnceConsumerLifecycleTest}} (5 tests, latches and {{Thread.join}}, 
> no sleeps): the thread ends when the CamelContext stops; when the route is 
> removed before it fired ({{delay=3600000}}); no thread left after 20 routes 
> were added, fired and removed; a route started again fires again; a route 
> fires again after a CamelContext restart. All 5 fail on main (3 with the 
> leaked non-daemon threads listed, 2 with the IllegalStateException) and pass 
> with the fix; camel-once 16/0.
> *How it was found*: a scan of the consumers for {{java.util.Timer}} and own 
> executors that outlive a route stop, while adding leak invariants (no task of 
> a pool after the route stop, pools released) to the deterministic simulation 
> worlds; a {{java.util.Timer}} is outside the harness, so the scan and a plain 
> test found it.
> *Affected*: 4.17.0 and later (4.17.x, 4.18.x, 4.22.x, 4.23.0, main; same code 
> since the component was added in CAMEL-22431).
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to