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

ASF GitHub Bot commented on CXF-7109:
-------------------------------------

GitHub user tadayosi opened a pull request:

    https://github.com/apache/cxf/pull/187

    [CXF-7109] ClientCallback may be invoked twice when Async HTTP Transport is 
used

    https://issues.apache.org/jira/browse/CXF-7109
    
    I think the best way to make a client callback invoked once and only once 
is to remove from the exchange immediately after its `handle***()` method is 
invoked once. It should prevent a client callback from being called more than 
once not only for the 
[CXF-7109](https://issues.apache.org/jira/browse/CXF-7109) case but also for 
any other potential cases where the callback may be invoked more than once 
accidentally.
    
    I added `remove(Class<T>)` to `Exchange` (`StringMap`) for convenience and 
symmetry. It is necessary to remove the callback right before calling its 
`handle***()`, as otherwise some other thread may grab it concurrently before 
the current thread invokes `handle***()`.
    
    I also added a test case 
`AsyncHTTPConduitTest#testCallAsyncCallbackInvokedOnlyOnce()`, but please note 
this test fails only on RHEL 6.8 even without this fix. In order to check if 
this fix is really effective, you need to run the test on RHEL 6.8 to compare 
the results.

You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/tadayosi/cxf CXF-7109

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/cxf/pull/187.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #187
    
----
commit 4eb81d3044c0f663d580cdbd3b611d5e3b1b4ac5
Author: Tadayoshi Sato <[email protected]>
Date:   2016-10-25T09:45:42Z

    [CXF-7109] ClientCallback may be invoked twice when Async HTTP Transport is 
used

----


> ClientCallback may be invoked twice when Async HTTP Transport is used
> ---------------------------------------------------------------------
>
>                 Key: CXF-7109
>                 URL: https://issues.apache.org/jira/browse/CXF-7109
>             Project: CXF
>          Issue Type: Bug
>          Components: Core, Transports
>    Affects Versions: 3.1.8
>         Environment: RHEL 6.8
>            Reporter: Tadayoshi Sato
>
> With Async HTTP Transport ({{cxf-rt-transports-http-hc}}) enabled, the 
> {{ClientCallback}} object passed for the invocation of the client may be 
> called twice when a failure occurs during the invocation:
> {code:java}
> Client client = ...
> client.invoke(new ClientCallback { ... }, opName, params);
> {code}
> At this moment, this issue is reproduced only on RHEL 6.8, but code analysis 
> shows that it's a general multithreading issue with Async HTTP Transport and 
> in theory it can happen on any platform.
> Here is what I've found with the code analysis:
> If for some reason the target endpoint is not reachable, this issue can 
> happen when the callback for Apache HC {{HttpAsyncClient}} \[1] is invoked 
> and thus shuts down {{SharedOutputBuffer}} earlier than {{HTTPConduit}} tries 
> to write it before closing the conduit itself \[2].
> \[1] 
> https://github.com/apache/cxf/blob/cxf-3.1.8/rt/transports/http-hc/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java#L464
> \[2] 
> https://github.com/apache/cxf/blob/cxf-3.1.8/rt/transports/http-hc/src/main/java/org/apache/cxf/transport/http/asyncclient/SharedOutputBuffer.java#L231
> When the above issue happens, the interceptor chain's fault observer is 
> eventually invoked twice, once from the response workqueue thread \[3] that 
> is spawn by the Apache HC {{HttpAsyncClient}} callback and the second time 
> from the requesting thread at the interceptor chain \[4]; Thus the client 
> callback is also invoked twice \[5]!
> \[3] 
> https://github.com/apache/cxf/blob/cxf-3.1.8/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java#L1177
> \[4] 
> https://github.com/apache/cxf/blob/cxf-3.1.8/core/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java#L366
> \[5] 
> https://github.com/apache/cxf/blob/cxf-3.1.8/core/src/main/java/org/apache/cxf/interceptor/ClientOutFaultObserver.java#L59
> Why it happens so reliably only on RHEL 6.8 is still unclear (probably due to 
> some thread scheduling logic specific to the kernel for RHEL 6.8), but since 
> it's essentially an ordering issue for two distinct threads, in theory it can 
> happen on any platforms. In general, CXF should really enforce that every 
> client callback be invoked once and only once.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to