[ 
https://issues.apache.org/jira/browse/CAMEL-24134?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18096832#comment-18096832
 ] 

Claus Ibsen commented on CAMEL-24134:
-------------------------------------

Fixed via https://github.com/apache/camel/pull/24797

> camel-resilience4j / camel-microprofile-fault-tolerance - Circuit Breaker 
> EIP: timed-out task writes results back to the original exchange, racing with 
> fallback processing
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24134
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24134
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-microprofile-fault-tolerance, eip
>    Affects Versions: 4.21.0
>            Reporter: Federico Mariani
>            Assignee: Claus Ibsen
>            Priority: Major
>             Fix For: 4.22.0
>
>
> In both Circuit Breaker implementations, the protected processor runs on a 
> correlated copy of the exchange, but the worker thread writes the outcome 
> back to the *original* exchange with no guard against the caller having 
> already moved on after a timeout.
> camel-resilience4j, {{ResilienceProcessor.processTask()}} (the identical 
> pattern exists in {{FaultToleranceProcessor.CircuitBreakerTask.call()}} with 
> SmallRye's thread offload):
> {code:java}
> // handle the processing result
> if (copy.getException() != null) {
>     exchange.setException(copy.getException());
> } else {
>     // copy the result as its regarded as success
>     ExchangeHelper.copyResults(exchange, copy);
>     
> exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_SUCCESSFUL_EXECUTION,
>  true);
>     ...
> }
> {code}
> When the TimeLimiter (or SmallRye timeout) fires, the calling thread 
> immediately runs the fallback and continues routing on the original exchange. 
> Meanwhile the worker thread - unless it happens to be blocked at an 
> interruptible point, and always when {{timeoutCancelRunningFuture=false}} - 
> eventually completes and executes the write-back above, concurrently mutating 
> the same original exchange:
> * it can overwrite the fallback result with the late result;
> * it can reinstate an exception after the fallback cleared it;
> * {{ExchangeHelper.copyResults}} is not atomic, so body/headers/properties 
> can interleave with the route's own processing.
> The exchange copy only protects against *downstream processors* mutating the 
> exchange during timeout processing (as the code comment says); the write-back 
> path itself is unguarded.
> Suggested fix: the worker must not touch the original exchange once the call 
> has timed out - e.g. a per-task completed/timed-out flag (CAS) checked before 
> the write-back, or perform the write-back on the caller side only when the 
> future completed within the timeout.
> _Filed by Claude Code on behalf of Federico Mariani (fmariani)_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to