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

Claus Ibsen reassigned CAMEL-24179:
-----------------------------------

    Assignee: Claus Ibsen  (was: Federico Mariani)

> camel-cxf/camel-cxfrs - continuation timeout races with in-flight async 
> processing (UoW closed twice, continuation double-resumed)
> ----------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24179
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24179
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-cxf
>            Reporter: Federico Mariani
>            Assignee: Claus Ibsen
>            Priority: Major
>
> *Severity:* High
> Affects both the SOAP consumer ({{CxfConsumer}}) and the cxfrs invoker 
> ({{CxfRsInvoker}}), which share the same continuation/async structure.
> h3. Problem 1 - timeout mutates and closes an Exchange still being processed
> In {{asyncInvoke}}, the new-request branch calls {{createUoW}}, 
> {{continuation.suspend(continuationTimeout)}} (default 30000 ms) and then 
> {{getAsyncProcessor().process(camelExchange, callback)}}. If the route runs 
> longer than the timeout, CXF resumes and the timeout branch runs:
> {code:java}
> camelExchange = (Exchange) continuation.getObject();
> camelExchange.setException(new ExchangeTimedOutException(camelExchange, 
> endpoint.getContinuationTimeout()));
> return returnResponse(cxfExchange, camelExchange);  // -> 
> doneUoW(camelExchange)
> {code}
> This mutates ({{setException}}) and closes the UnitOfWork ({{doneUoW}}) of 
> the *same* {{camelExchange}} the worker thread is still processing. Nothing 
> synchronizes the two threads on Exchange state 
> ({{synchronized(continuation)}} guards only the continuation). With pooled 
> exchanges (the modern default), {{doneUoW}} can reset/recycle the Exchange 
> while the worker still holds it -> cross-request state corruption under load.
> h3. Problem 2 - unconditional resume after timeout
> The async {{done()}} callback always calls {{continuation.resume()}} with no 
> {{isResumed()}}/{{isTimeout()}} guard. After a timeout already produced a 
> response and closed the UoW, the late completion resumes again; CXF 
> re-invokes, {{returnResponse}}/{{doneUoW}} run a second time ({{uow.done()}} 
> is not idempotent), potentially writing a second response onto an 
> already-completed servlet response.
> h3. Location
> {{camel-cxf-rest/.../jaxrs/CxfRsInvoker.java}} ~100-133 and 
> {{camel-cxf-soap/.../jaxws/CxfConsumer.java}} ~198-230.
> h3. Fix
> Redesign timeout-vs-callback completion so exactly one of {timeout, normal 
> completion} owns writing the response and closing the UoW:
> * on timeout, do not mutate/close the in-flight Exchange; mark the 
> continuation abandoned and let the async {{done()}} close the UoW once;
> * guard {{done()}} to resume only when the continuation is still pending 
> ({{!continuation.isResumed() && !continuation.isTimeout()}}).
> h3. Reproduction
> Set {{continuationTimeout}} low (e.g. 500 ms) and a route with a {{delay}} 
> longer than that; assert a single response, a single UoW completion, and no 
> state bleed onto a subsequently-pooled exchange. (Timing-sensitive; the two 
> problems are one coupled fix.)
> ----
> _Filed by Claude Code (Claude Fable) on behalf of Federico Mariani (GitHub: 
> Croway). Findings from an AI-assisted code review of the camel-cxf component 
> family; each item was verified against the current source and git history. 
> Items marked *[reproducer attached]* include a failing JUnit test that 
> demonstrates the defect._



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

Reply via email to