Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-7037

@Suspended can be broken on tomcat

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.7
    • Fix Version/s: 3.1.8, 3.0.11, 3.2.0
    • Component/s: None
    • Labels:
      None
    • Estimated Complexity:
      Unknown

      Description

      For AsyncContext usages, tomcat ensures the non container threads wait for the container thread to exit the execution (the one starting the async context) to avoid concurrency issue.

      For cxf it means you can resume() in a user thread on an AsyncResponse while you execute AsyncResponseImpl.suspendContinuationIfNeeded().

      This can lead to a lock preventing the request to complete.

      Here is a sample thread:

      "managed-thread-3@7750" daemon prio=5 tid=0x48 nid=NA waiting
        java.lang.Thread.State: WAITING
           blocks http-nio-24622-exec-3@7702
            at java.lang.Object.wait(Object.java:-1)
            at java.lang.Object.wait(Object.java:502)
            at org.apache.coyote.AsyncStateMachine.pauseNonContainerThread(AsyncStateMachine.java:452)
            at org.apache.coyote.AsyncStateMachine.asyncDispatch(AsyncStateMachine.java:315)
            at org.apache.coyote.http11.Http11Processor.action(Http11Processor.java:858)
            at org.apache.coyote.Request.action(Request.java:390)
            at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:203)
            - locked <0x21ed> (a java.lang.Object)
            at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:171)
            at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:165)
            at org.apache.openejb.server.httpd.EEFilter$AsynContextWrapper.dispatch(EEFilter.java:171)
            at org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.redispatch(Servlet3ContinuationProvider.java:125)
            at org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.resume(Servlet3ContinuationProvider.java:131)
            at org.apache.cxf.jaxrs.impl.AsyncResponseImpl.doResumeFinal(AsyncResponseImpl.java:96)
            - locked <0x2196> (a org.apache.cxf.jaxrs.impl.AsyncResponseImpl)
            at org.apache.cxf.jaxrs.impl.AsyncResponseImpl.doResume(AsyncResponseImpl.java:89)
            at org.apache.cxf.jaxrs.impl.AsyncResponseImpl.resume(AsyncResponseImpl.java:73)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor.lambda$async$0(AsyncInterceptor.java:63)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$$Lambda$55.375198754.run(Unknown Source:-1)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$TransactionProvider.run(AsyncInterceptor.java:148)
            at sun.reflect.GeneratedMethodAccessor95.invoke(Unknown Source:-1)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.apache.webbeans.intercept.AbstractInvocationContext.directProceed(AbstractInvocationContext.java:113)
            at org.apache.webbeans.intercept.AbstractInvocationContext.proceed(AbstractInvocationContext.java:106)
            at org.apache.webbeans.intercept.InterceptorInvocationContext.proceed(InterceptorInvocationContext.java:67)
            at org.apache.openejb.cdi.transactional.InterceptorBase.intercept(InterceptorBase.java:66)
            at org.apache.openejb.cdi.transactional.RequiredInterceptor.intercept(RequiredInterceptor.java:35)
            at sun.reflect.GeneratedMethodAccessor85.invoke(Unknown Source:-1)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.apache.webbeans.component.InterceptorBean.intercept(InterceptorBean.java:136)
            at org.apache.webbeans.intercept.InterceptorInvocationContext.proceed(InterceptorInvocationContext.java:63)
            at org.apache.webbeans.intercept.DefaultInterceptorHandler.invoke(DefaultInterceptorHandler.java:139)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$TransactionProvider$$OwbInterceptProxy0.run(com/github/rmannibucau/rblog/jaxrs/async/AsyncInterceptor$TransactionProvider.java:-1)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$TransactionProvider$$OwbNormalScopeProxy0.run(com/github/rmannibucau/rblog/jaxrs/async/AsyncInterceptor$TransactionProvider.java:-1)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas.lambda$runInTransaction$6(AsyncInterceptor.java:130)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas$$Lambda$56.1727885795.run(Unknown Source:-1)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas.lambda$toJaxRs$7(AsyncInterceptor.java:136)
            at com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas$$Lambda$57.1956863343.run(Unknown Source:-1)
            at org.apache.openejb.threads.task.CURunnable$1.call(CURunnable.java:35)
            at org.apache.openejb.threads.task.CURunnable$1.call(CURunnable.java:32)
            at org.apache.openejb.threads.task.CUTask.invoke(CUTask.java:89)
            at org.apache.openejb.threads.task.CURunnable.run(CURunnable.java:32)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
            at java.util.concurrent.FutureTask.run(FutureTask.java:266)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
            at java.lang.Thread.run(Thread.java:745)
      
      "http-nio-24622-exec-3@7702" daemon prio=5 tid=0x41 nid=NA waiting for monitor entry
        java.lang.Thread.State: BLOCKED
           waiting for managed-thread-3@7750 to release lock on <0x2196> (a org.apache.cxf.jaxrs.impl.AsyncResponseImpl)
            at org.apache.cxf.jaxrs.impl.AsyncResponseImpl.suspendContinuationIfNeeded(AsyncResponseImpl.java:263)
            at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:191)
      

      Solution would be to not synchronize both method and probably move to a volatile state

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                sergey_beryozkin Sergey Beryozkin
                Reporter:
                romain.manni-bucau Romain Manni-Bucau
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: