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

Work on CAMEL-26541 started by shashank.
----------------------------------------
> camel-core - interceptSendToEndpoint: an endpoint created while a route 
> starts or stops gets the wrong interceptors
> -------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-26541
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26541
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> Found with a TLA+ model of {{InterceptSendToEndpointManager}} (CAMEL-25140): 
> a thread that creates an endpoint (a {{toD}} to an endpoint that is not in 
> the registry yet) and the lifecycle thread that starts, stops, removes and 
> adds again a route with {{interceptSendToEndpoint}}. Then reproduced on the 
> real classes.
> Since CAMEL-25140 a route registers its interceptor when it starts and 
> unregisters it when it stops. {{register}} and {{unregister}} run under the 
> manager's lock and update the wrapped endpoints that are *in the endpoint 
> registry*. A new endpoint gets the interceptors in {{registerEndpoint}} (the 
> endpoint strategy), without that lock, and 
> {{AbstractCamelContext.addEndpointToRegistry}} puts it in the registry only 
> after the strategies returned. A route that starts or stops between the two 
> steps does not see the new endpoint:
> * *start*: the running route's interceptor is missing on the endpoint, so its 
> {{interceptSendToEndpoint}} does not apply to it.
> * *stop or remove*: the stopped route's interceptor stays on the endpoint. It 
> runs on the stopped route's error handler, so the sends that use it fail with 
> {{RouteStoppingException}} ("The exchange cannot continue: its route is being 
> stopped or reloaded"): the sends of routes without an interceptor of their 
> own and of a {{ProducerTemplate}}, including the send that created the 
> endpoint. After a stop this lasts until the route starts again. After a 
> remove it stays when the route is added again, and the new route's own sends 
> fail too (the old interceptor has the same route id and runs first).
> Short trace (start):
> {noformat}
> toD thread:  registerEndpoint: wrapper created, registrations = []  (no 
> interceptor added)
> lifecycle:   startRoute -> register: registrations = [r]; scan registry 
> (endpoint not there)
> toD thread:  endpoints.put(wrapper)                                    -> 
> route r running, endpoint not intercepted
> {noformat}
> Reproducer (the test pauses the thread that creates the endpoint just before 
> {{endpoints.put}}, with an endpoint registry that waits on a latch, and 
> starts or stops the route meanwhile):
> {code:java}
> // builder 1
> interceptSendToEndpoint("mock:dyn*").to("mock:intercepted");
> from("direct:start").routeId("start").toD("mock:${header.name}");
> // builder 2, no interceptor
> from("direct:other").routeId("other").toD("mock:${header.name}");
> // thread A: template.sendBodyAndHeader("direct:other", "Hello", "name", 
> "dyn1")  -> paused before endpoints.put
> // main:     routeController.startRoute("start")  (it was stopped before)
> // release A
> template.sendBodyAndHeader("direct:start", "Bye", "name", "dyn1");   // 
> mock:intercepted gets nothing
> {code}
> On main (e05c5485d507) the start, stop and remove-and-add-again cases fail; 
> the same steps one after the other pass. Without the latch, a stress loop 
> (new {{toD}} endpoints while the route starts and stops) hit it on main too. 
> The window is small, but route reloads and route policies stop and start 
> routes under traffic, and the result stays (until the endpoint is created 
> again or, for a missing interceptor, until a route with 
> {{interceptSendToEndpoint}} starts).
> *Proposal*
> * {{registerEndpoint}} wraps the endpoint under the manager's lock (a read 
> lock; {{addPattern}}, {{register}} and {{unregister}} take the write lock), 
> and the manager remembers the wrappers it returns (weak keys, as a {{toD}} 
> endpoint can be evicted from the registry), so {{register}} and 
> {{unregister}} also update the wrappers that are not in the registry yet. 
> Endpoints that match no pattern take no lock. This keeps the CAMEL-25140 
> design; the model holds with it.
> * Not covered (it would need the registry put under the same lock): a route 
> added at runtime with a new uri pattern, while a matching endpoint is being 
> created, can leave that endpoint unwrapped until the next start of a route 
> with {{interceptSendToEndpoint}}.
> Affects: 4.23.0 (CAMEL-25140), main. CAMEL-25141 would narrow the stop/remove 
> case to the route's own sends, not remove it.
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to