This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new eb2f10067c39 CAMEL-23681: Fix race condition in DefaultUnitOfWork 
route stack
eb2f10067c39 is described below

commit eb2f10067c39eab410282bfec2155fc1d147b295
Author: Guillaume Nodet <[email protected]>
AuthorDate: Fri Jun 5 10:16:48 2026 +0200

    CAMEL-23681: Fix race condition in DefaultUnitOfWork route stack
    
    The CAMEL-23686 optimization replaced ConcurrentLinkedDeque with a plain
    Route field + lazy ArrayDeque, reintroducing the race condition from
    CAMEL-22533 when split().parallelProcessing().shareUnitOfWork() causes
    concurrent access. Protect route stack operations (getRoute, pushRoute,
    popRoute, routeStackLevel) with the existing ReentrantLock while
    preserving the memory optimization.
    
    Closes #23777
---
 .../camel/impl/engine/DefaultUnitOfWork.java       | 79 +++++++++++++++-------
 1 file changed, 54 insertions(+), 25 deletions(-)

diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultUnitOfWork.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultUnitOfWork.java
index bcb35ca1f866..60ce4d4b8c3e 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultUnitOfWork.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultUnitOfWork.java
@@ -371,53 +371,82 @@ public class DefaultUnitOfWork implements UnitOfWork {
 
     @Override
     public Route getRoute() {
-        return route;
+        lock.lock();
+        try {
+            return route;
+        } finally {
+            lock.unlock();
+        }
     }
 
     @Override
     public void pushRoute(Route route) {
-        if (this.route == null) {
-            this.route = route;
-        } else {
-            if (routeStack == null) {
-                routeStack = new ArrayDeque<>();
+        lock.lock();
+        try {
+            if (this.route == null) {
+                this.route = route;
+            } else {
+                if (routeStack == null) {
+                    routeStack = new ArrayDeque<>();
+                }
+                routeStack.push(this.route);
+                this.route = route;
             }
-            routeStack.push(this.route);
-            this.route = route;
+        } finally {
+            lock.unlock();
         }
     }
 
     @Override
     public Route popRoute() {
-        Route old = this.route;
-        if (routeStack != null && !routeStack.isEmpty()) {
-            this.route = routeStack.pop();
-        } else {
-            this.route = null;
+        lock.lock();
+        try {
+            Route old = this.route;
+            if (routeStack != null && !routeStack.isEmpty()) {
+                this.route = routeStack.pop();
+            } else {
+                this.route = null;
+            }
+            return old;
+        } finally {
+            lock.unlock();
         }
-        return old;
     }
 
     @Override
     public int routeStackLevel() {
+        lock.lock();
+        try {
+            return routeStackSize();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    private int routeStackSize() {
         return (route != null ? 1 : 0) + (routeStack != null ? 
routeStack.size() : 0);
     }
 
     public int routeStackLevel(boolean includeRouteTemplate, boolean 
includeKamelet) {
-        if (includeKamelet && includeRouteTemplate) {
-            return routeStackLevel();
-        }
+        lock.lock();
+        try {
+            if (includeKamelet && includeRouteTemplate) {
+                return routeStackSize();
+            }
 
-        int level = 0;
-        if (route != null) {
-            level += countRoute(route, includeRouteTemplate, includeKamelet);
-        }
-        if (routeStack != null) {
-            for (Route r : routeStack) {
-                level += countRoute(r, includeRouteTemplate, includeKamelet);
+            int level = 0;
+            if (route != null) {
+                level += countRoute(route, includeRouteTemplate, 
includeKamelet);
             }
+            if (routeStack != null) {
+                for (Route r : routeStack) {
+                    level += countRoute(r, includeRouteTemplate, 
includeKamelet);
+                }
+            }
+            return level;
+        } finally {
+            lock.unlock();
         }
-        return level;
     }
 
     private static int countRoute(Route r, boolean includeRouteTemplate, 
boolean includeKamelet) {

Reply via email to