allthingssecurity opened a new pull request, #29530: URL: https://github.com/apache/camel/pull/29530
# Description [CAMEL-26755](https://issues.apache.org/jira/browse/CAMEL-26755) `AbstractCamelClusterService.getView` takes a reference on the view of the namespace, and the first reference starts the view. `ReferenceCount.retain` increases the count before it runs the start, and nothing gave the reference back when the start threw. The caller got the exception and held no reference, but the count stayed at 1: - the next `getView` only increased the count, so it got a view that was never started; - for a `master:` route (the consumer takes the view when it starts) started again by an operator or by the supervising route controller, the route was reported started, but the node never took part in the election, also as the only node and after the cause was gone; - a clustered route added later on the same namespace (its `ClusteredRoutePolicy` takes the view when the route is created) was never started either; - `releaseView` could no longer bring the count to 0, so the view was never stopped; - a stop and start of the cluster service (CamelContext restart, or the JMX operations) starts every view with references since CAMEL-25089, so it started this view that no route uses, and the node could take the leadership of a namespace it does not use, keeping the route of the other nodes from running. A view start fails when the backend is not reachable yet (`ConsulClusterView` creates a session, `JGroupsRaftClusterView` connects, `InfinispanRemoteClusterView` writes to the remote cache), or on an invalid setting (`FileLockClusterView` rejects an `acquireLockInterval` below 1 millisecond). Change: when the start throws, the view holder gives the reference back and rethrows. Giving it back runs the release callback, which stops the view; a view whose start failed is in the `Failed` state, which `stop()` treats as already stopped, and a later start initializes it again. All changes of the count happen under the service's write lock, so nobody can take a reference in between. The fix is in the view holder and not in `ReferenceCount.retain`, as `ReferenceCount` is lock-free and an undo there is only safe when the caller serializes the calls, as this service does. Left as it was, for a follow-up JIRA: `ClusteredRoutePolicy` has its own reference count around `retainClusterView` with the same shape (it only matters for a policy shared by several routes; `ClusteredRoutePolicyFactory` and `ClusteredRouteController` create one policy per route), and `EhcacheManager` uses `ReferenceCount` the same way. Test, in `ClusterServiceViewTest` (in-JVM test service whose view start can be made to fail): - `testViewReferencesWhenStartFails`: the first `getView` fails; the next `getView` must return a started view; releasing it must stop it; a stop and start of the service must not start it again. On main the test fails at its second step: the second `getView` returns a view that is not started (status `Stopped`, its start having failed). With the fix: camel-core `org.apache.camel.cluster` tests 40/0 (and 50/0 together with `org.apache.camel.component.file.cluster`, before the test's exception check was tightened), camel-file cluster tests 16/0, camel-master 32/0 (it uses the cluster services through `MasterConsumer`), `ManagedClusterServiceTest` 1/0, and `ClusterServiceViewTest` (6 tests) 120/120 over 20 runs in one JVM. The reference leak is on every maintained branch; the restart symptom needs CAMEL-25089 (4.23.0), so a backport to `camel-4.23.x` applies as is. Found with Specula (TLA+ model checked against traces of the real code) and confirmed with the test above. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it): [CAMEL-26755](https://issues.apache.org/jira/browse/CAMEL-26755). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built the core modules with the formatter and import-sort plugins and ran the cluster tests of camel-core, camel-master and camel-management; no generated file changes. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
